..
This commit is contained in:
parent
ce7c53bf1a
commit
c82a582a94
11 changed files with 435 additions and 160 deletions
|
@ -1,7 +1,25 @@
|
|||
|
||||
SUBDIRS=uislave
|
||||
|
||||
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
||||
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_COMPILE=1
|
||||
|
||||
## convenience libraries lead to annoying slow compiles, plus we want
|
||||
## to be extra-hacky by using #ifdef METACITY_COMPILE, ergo cheesy
|
||||
## hack that follows.
|
||||
copied_sources= \
|
||||
messagequeue.h \
|
||||
messagequeue.c
|
||||
copied_sources_deps= \
|
||||
$(srcdir)/uislave/messagequeue.h \
|
||||
$(srcdir)/uislave/messagequeue.c
|
||||
|
||||
BUILT_SOURCES=$(copied_sources)
|
||||
|
||||
$(copied_sources): $(copied_sources_deps)
|
||||
for I in $(copied_sources); do \
|
||||
rm -f $$I ; \
|
||||
cp $(srcdir)/uislave/$$I . ; \
|
||||
done
|
||||
|
||||
metacity_SOURCES= \
|
||||
api.c \
|
||||
|
@ -27,7 +45,8 @@ metacity_SOURCES= \
|
|||
util.c \
|
||||
util.h \
|
||||
window.c \
|
||||
window.h
|
||||
window.h \
|
||||
$(copied_sources)
|
||||
|
||||
bin_PROGRAMS=metacity
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#! /bin/bash
|
||||
|
||||
Xnest :1 -scrns 2 -geometry 270x270 &
|
||||
if test -z "$SCREENS"; then
|
||||
SCREENS=2
|
||||
fi
|
||||
Xnest :1 -scrns $SCREENS -geometry 270x270 &
|
||||
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute gdb ./metacity
|
||||
killall Xnest
|
||||
|
|
338
src/uislave.c
338
src/uislave.c
|
@ -25,6 +25,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -34,9 +35,6 @@ typedef enum
|
|||
} ReadResult;
|
||||
|
||||
static void respawn_child (MetaUISlave *uislave);
|
||||
static gboolean output_callback (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data);
|
||||
static gboolean error_callback (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data);
|
||||
|
@ -149,8 +147,6 @@ respawn_child (MetaUISlave *uislave)
|
|||
uislave->child_pid = child_pid;
|
||||
uislave->in_pipe = inpipe;
|
||||
uislave->err_pipe = errpipe;
|
||||
uislave->out_poll.fd = outpipe;
|
||||
uislave->out_poll.events = G_IO_IN;
|
||||
|
||||
uislave->err_channel = g_io_channel_unix_new (errpipe);
|
||||
|
||||
|
@ -159,6 +155,11 @@ respawn_child (MetaUISlave *uislave)
|
|||
error_callback,
|
||||
uislave);
|
||||
|
||||
uislave->out_poll.fd = outpipe;
|
||||
uislave->out_poll.events = G_IO_IN;
|
||||
|
||||
g_source_add_poll ((GSource*)uislave, &uislave->out_poll);
|
||||
|
||||
meta_verbose ("Spawned UI slave with PID %d\n", uislave->child_pid);
|
||||
}
|
||||
else
|
||||
|
@ -182,42 +183,59 @@ append_pending (MetaUISlave *uislave)
|
|||
needed = MIN (needed, uislave->buf->len);
|
||||
|
||||
/* Move data from buf to current_message */
|
||||
g_string_append_len (uislave->current_message,
|
||||
uislave->buf->str,
|
||||
needed);
|
||||
g_string_erase (uislave->buf,
|
||||
0, needed);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_callback (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
/* Read messages from slave */
|
||||
MetaUISlave *uislave;
|
||||
ReadResult res;
|
||||
|
||||
uislave = data;
|
||||
|
||||
res = read_data (uislave->buf, uislave->out_pipe);
|
||||
|
||||
switch (res)
|
||||
if (needed > 0)
|
||||
{
|
||||
case READ_OK:
|
||||
meta_verbose ("Read data from slave, %d bytes in buffer\n",
|
||||
uislave->buf->len);
|
||||
break;
|
||||
case READ_EOF:
|
||||
meta_verbose ("EOF reading stdout from slave process\n");
|
||||
break;
|
||||
|
||||
case READ_FAILED:
|
||||
/* read_data printed the error */
|
||||
break;
|
||||
meta_verbose ("Moving %d bytes from buffer to current incomplete message\n",
|
||||
needed);
|
||||
g_string_append_len (uislave->current_message,
|
||||
uislave->buf->str,
|
||||
needed);
|
||||
g_string_erase (uislave->buf,
|
||||
0, needed);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
g_assert (uislave->current_message->len <= uislave->current_required_len);
|
||||
|
||||
if (uislave->current_required_len > 0 &&
|
||||
uislave->current_message->len == uislave->current_required_len)
|
||||
{
|
||||
MetaMessage *message;
|
||||
MetaMessageFooter *footer;
|
||||
|
||||
message = g_new (MetaMessage, 1);
|
||||
|
||||
memcpy (message,
|
||||
uislave->current_message->str, uislave->current_message->len);
|
||||
|
||||
if (message->header.length != uislave->current_required_len)
|
||||
meta_bug ("Message length changed?\n");
|
||||
|
||||
if (message->header.serial != uislave->last_serial)
|
||||
meta_bug ("Message serial changed?\n");
|
||||
|
||||
footer = META_MESSAGE_FOOTER (message);
|
||||
|
||||
if (footer->checksum == META_MESSAGE_CHECKSUM (message))
|
||||
{
|
||||
g_queue_push_tail (uislave->queue, message);
|
||||
|
||||
meta_verbose ("Added %d-byte message serial %d to queue\n",
|
||||
uislave->current_message->len, message->header.serial);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_bug ("Bad checksum %d on %d-byte message from UI slave\n",
|
||||
footer->checksum, uislave->current_message->len);
|
||||
}
|
||||
|
||||
uislave->current_required_len = 0;
|
||||
g_string_truncate (uislave->current_message, 0);
|
||||
}
|
||||
else if (uislave->current_required_len > 0)
|
||||
{
|
||||
meta_verbose ("Storing %d bytes of incomplete message\n",
|
||||
uislave->current_message->len);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -232,7 +250,7 @@ error_callback (GIOChannel *source,
|
|||
int n;
|
||||
|
||||
uislave = data;
|
||||
|
||||
|
||||
/* Classic loop from Stevens */
|
||||
n = read (uislave->err_pipe, buf, BUFSIZE);
|
||||
if (n > 0)
|
||||
|
@ -250,110 +268,147 @@ error_callback (GIOChannel *source,
|
|||
|
||||
static void
|
||||
mq_queue_messages (MetaUISlave *uislave)
|
||||
{
|
||||
if (uislave->buf->len == 0)
|
||||
return;
|
||||
|
||||
if (uislave->current_message->len > 0)
|
||||
{
|
||||
if (uislave->out_poll.revents & G_IO_IN)
|
||||
{
|
||||
/* We had a pending message. */
|
||||
append_pending (uislave);
|
||||
}
|
||||
else if (uislave->buf->len > META_MESSAGE_ESCAPE_LEN)
|
||||
{
|
||||
/* See if we can start a current message */
|
||||
const char *p;
|
||||
int esc_pos;
|
||||
const char *esc;
|
||||
MetaMessageHeader header;
|
||||
ReadResult res;
|
||||
|
||||
res = read_data (uislave->buf, uislave->out_poll.fd);
|
||||
|
||||
/* note that the string from the UI slave includes the nul byte */
|
||||
esc = META_MESSAGE_ESCAPE;
|
||||
|
||||
esc_pos = 0;
|
||||
p = uislave->buf->str;
|
||||
while (p != (uislave->buf->str + uislave->buf->len) &&
|
||||
esc_pos < META_MESSAGE_ESCAPE_LEN)
|
||||
switch (res)
|
||||
{
|
||||
if (*p != esc[esc_pos])
|
||||
esc_pos = 0;
|
||||
else
|
||||
++esc_pos;
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
if (esc_pos == META_MESSAGE_ESCAPE_LEN)
|
||||
{
|
||||
/* We found an entire escape sequence; can safely toss
|
||||
* out the entire buffer before it
|
||||
*/
|
||||
int ignored;
|
||||
|
||||
ignored = p - uislave->buf->str;
|
||||
ignored -= META_MESSAGE_ESCAPE_LEN;
|
||||
|
||||
g_assert (ignored >= 0);
|
||||
|
||||
if (ignored > 0)
|
||||
{
|
||||
meta_verbose ("Ignoring %d bytes from UI slave\n",
|
||||
ignored);
|
||||
|
||||
g_string_erase (uislave->buf, 0, ignored);
|
||||
}
|
||||
}
|
||||
else if (esc_pos == 0)
|
||||
{
|
||||
/* End of buffer doesn't begin an escape sequence;
|
||||
* toss out entire buffer.
|
||||
*/
|
||||
meta_verbose ("Ignoring %d bytes from UI slave\n",
|
||||
case READ_OK:
|
||||
meta_verbose ("Read data from slave, %d bytes in buffer\n",
|
||||
uislave->buf->len);
|
||||
g_string_truncate (uislave->buf, 0);
|
||||
break;
|
||||
case READ_EOF:
|
||||
meta_verbose ("EOF reading stdout from slave process\n");
|
||||
break;
|
||||
|
||||
case READ_FAILED:
|
||||
/* read_data printed the error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (uislave->buf->len > 0)
|
||||
{
|
||||
if (uislave->current_required_len > 0)
|
||||
{
|
||||
/* We had a pending message. */
|
||||
append_pending (uislave);
|
||||
}
|
||||
else if (uislave->buf->len > META_MESSAGE_ESCAPE_LEN)
|
||||
{
|
||||
/* See if we can start a current message */
|
||||
const char *p;
|
||||
int esc_pos;
|
||||
const char *esc;
|
||||
MetaMessageHeader header;
|
||||
|
||||
if (uislave->buf->len < (META_MESSAGE_ESCAPE_LEN + sizeof (MetaMessageHeader)))
|
||||
return; /* Not enough data yet. */
|
||||
g_assert (uislave->current_required_len == 0);
|
||||
g_assert (uislave->current_message->len == 0);
|
||||
|
||||
meta_verbose ("Scanning for escape sequence in %d bytes\n",
|
||||
uislave->buf->len);
|
||||
|
||||
/* note that the data from the UI slave includes the nul byte */
|
||||
esc = META_MESSAGE_ESCAPE;
|
||||
|
||||
esc_pos = -1;
|
||||
p = uislave->buf->str;
|
||||
while (p != (uislave->buf->str + uislave->buf->len) &&
|
||||
esc_pos < META_MESSAGE_ESCAPE_LEN)
|
||||
{
|
||||
++esc_pos;
|
||||
if (*p != esc[esc_pos])
|
||||
esc_pos = -1;
|
||||
|
||||
memcpy (&header, uislave->buf->str + META_MESSAGE_ESCAPE_LEN, sizeof (MetaMessageHeader));
|
||||
++p;
|
||||
}
|
||||
|
||||
/* Length includes the header even though it's in the header. */
|
||||
meta_verbose ("Read header code: %d length: %d from UI slave\n",
|
||||
header.message_code, header.length);
|
||||
if (esc_pos == META_MESSAGE_ESCAPE_LEN)
|
||||
{
|
||||
/* We found an entire escape sequence; can safely toss
|
||||
* out the entire buffer before it
|
||||
*/
|
||||
int ignored;
|
||||
|
||||
uislave->current_required_len = header.length;
|
||||
g_string_erase (uislave->buf, 0, META_MESSAGE_ESCAPE_LEN);
|
||||
ignored = p - uislave->buf->str;
|
||||
ignored -= META_MESSAGE_ESCAPE_LEN;
|
||||
|
||||
append_pending (uislave);
|
||||
g_assert (ignored >= 0);
|
||||
|
||||
if (ignored > 0)
|
||||
{
|
||||
g_string_erase (uislave->buf, 0, ignored);
|
||||
meta_verbose ("Ignoring %d bytes before escape, new buffer len %d\n",
|
||||
ignored, uislave->buf->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (p == (uislave->buf->str + META_MESSAGE_ESCAPE_LEN));
|
||||
}
|
||||
}
|
||||
else if (esc_pos < 0)
|
||||
{
|
||||
/* End of buffer doesn't begin an escape sequence;
|
||||
* toss out entire buffer.
|
||||
*/
|
||||
meta_verbose ("Emptying %d-byte buffer not containing escape sequence\n",
|
||||
uislave->buf->len);
|
||||
g_string_truncate (uislave->buf, 0);
|
||||
goto need_more_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Buffer ends with partial escape sequence: '%s'\n",
|
||||
uislave->buf->str + (uislave->buf->len - esc_pos));
|
||||
goto need_more_data;
|
||||
}
|
||||
|
||||
g_assert (strcmp (uislave->buf->str, META_MESSAGE_ESCAPE) == 0);
|
||||
|
||||
if (uislave->buf->len < (META_MESSAGE_ESCAPE_LEN + sizeof (MetaMessageHeader)))
|
||||
{
|
||||
meta_verbose ("Buffer has full escape sequence but lacks header\n");
|
||||
goto need_more_data;
|
||||
}
|
||||
|
||||
g_string_erase (uislave->buf, 0, META_MESSAGE_ESCAPE_LEN);
|
||||
meta_verbose ("Stripped escape off front of buffer, new buffer len %d\n",
|
||||
uislave->buf->len);
|
||||
|
||||
g_assert (uislave->buf->len >= sizeof (MetaMessageHeader));
|
||||
|
||||
memcpy (&header, uislave->buf->str, sizeof (MetaMessageHeader));
|
||||
|
||||
/* Length includes the header even though it's in the header. */
|
||||
meta_verbose ("Read header, code: %d length: %d serial: %d\n",
|
||||
header.message_code, header.length, header.serial);
|
||||
|
||||
if (header.serial != uislave->last_serial + 1)
|
||||
meta_bug ("Wrong message serial number %d from UI slave!\n", header.serial);
|
||||
|
||||
uislave->last_serial = header.serial;
|
||||
uislave->current_required_len = header.length;
|
||||
|
||||
append_pending (uislave);
|
||||
}
|
||||
else
|
||||
goto need_more_data;
|
||||
}
|
||||
|
||||
g_assert (uislave->current_message->len <= uislave->current_required_len);
|
||||
|
||||
if (uislave->current_required_len > 0 &&
|
||||
uislave->current_message->len == uislave->current_required_len)
|
||||
{
|
||||
MetaMessage *message;
|
||||
|
||||
message = g_new (MetaMessage, 1);
|
||||
|
||||
memcpy (message,
|
||||
uislave->current_message->str, uislave->current_message->len);
|
||||
|
||||
g_queue_push_tail (uislave->queue, message);
|
||||
|
||||
meta_verbose ("Added %d-byte message to queue\n",
|
||||
uislave->current_message->len);
|
||||
|
||||
uislave->current_required_len = 0;
|
||||
g_string_truncate (uislave->current_message, 0);
|
||||
}
|
||||
need_more_data:
|
||||
return;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mq_messages_pending (MetaUISlave *uislave)
|
||||
{
|
||||
return uislave->queue->length > 0 || uislave->buf->len > 0;
|
||||
return uislave->queue->length > 0 ||
|
||||
uislave->buf->len > 0 ||
|
||||
uislave->current_message->len > 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -364,6 +419,8 @@ mq_prepare (GSource *source, gint *timeout)
|
|||
uislave = (MetaUISlave*) source;
|
||||
|
||||
*timeout = -1;
|
||||
|
||||
mq_queue_messages (uislave);
|
||||
|
||||
return mq_messages_pending (uislave);
|
||||
}
|
||||
|
@ -372,8 +429,11 @@ static gboolean
|
|||
mq_check (GSource *source)
|
||||
{
|
||||
MetaUISlave *uislave;
|
||||
|
||||
|
||||
uislave = (MetaUISlave*) source;
|
||||
|
||||
mq_queue_messages (uislave);
|
||||
uislave->out_poll.revents = 0;
|
||||
|
||||
return mq_messages_pending (uislave);
|
||||
}
|
||||
|
@ -384,8 +444,6 @@ mq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
|
|||
MetaUISlave *uislave;
|
||||
|
||||
uislave = (MetaUISlave*) source;
|
||||
|
||||
mq_queue_messages (uislave);
|
||||
|
||||
if (uislave->queue->length > 0)
|
||||
{
|
||||
|
@ -411,20 +469,17 @@ mq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
|
|||
static void
|
||||
kill_child (MetaUISlave *uislave)
|
||||
{
|
||||
if (uislave->outwatch != 0)
|
||||
g_source_remove (uislave->outwatch);
|
||||
|
||||
if (uislave->errwatch != 0)
|
||||
g_source_remove (uislave->errwatch);
|
||||
|
||||
if (uislave->out_channel)
|
||||
g_io_channel_unref (uislave->out_channel);
|
||||
g_source_remove (uislave->errwatch);
|
||||
|
||||
if (uislave->err_channel)
|
||||
g_io_channel_unref (uislave->err_channel);
|
||||
|
||||
if (uislave->out_pipe >= 0)
|
||||
close (uislave->out_pipe);
|
||||
if (uislave->out_poll.fd >= 0)
|
||||
{
|
||||
g_source_remove_poll ((GSource*)uislave, &uislave->out_poll);
|
||||
close (uislave->out_poll.fd);
|
||||
}
|
||||
|
||||
if (uislave->in_pipe >= 0)
|
||||
close (uislave->in_pipe);
|
||||
|
@ -467,14 +522,13 @@ reset_vals (MetaUISlave *uislave)
|
|||
{
|
||||
uislave->child_pid = 0;
|
||||
uislave->in_pipe = -1;
|
||||
uislave->out_pipe = -1;
|
||||
uislave->err_pipe = -1;
|
||||
uislave->out_poll.fd = -1;
|
||||
uislave->no_respawn = FALSE;
|
||||
uislave->out_channel = NULL;
|
||||
uislave->err_channel = NULL;
|
||||
uislave->outwatch = 0;
|
||||
uislave->errwatch = 0;
|
||||
uislave->current_required_len = 0;
|
||||
uislave->last_serial = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -503,7 +557,7 @@ static ReadResult
|
|||
read_data (GString *str,
|
||||
gint fd)
|
||||
{
|
||||
#define BUFSIZE 16
|
||||
#define BUFSIZE 4000
|
||||
gint bytes;
|
||||
gchar buf[BUFSIZE];
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ struct _MetaUISlave
|
|||
GString *buf;
|
||||
GString *current_message;
|
||||
int current_required_len;
|
||||
int last_serial;
|
||||
/* if we determine that our available slave is hosed,
|
||||
* set this bit.
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,9 @@ INCLUDES=@UISLAVE_CFLAGS@ -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
|||
metacity_uislave_SOURCES = \
|
||||
main.c \
|
||||
messages.c \
|
||||
messages.h
|
||||
messages.h \
|
||||
messagequeue.c \
|
||||
messagequeue.h
|
||||
|
||||
libexec_PROGRAMS=metacity-uislave
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
@ -50,13 +51,15 @@ main (int argc, char **argv)
|
|||
|
||||
/* report our nature to the window manager */
|
||||
meta_message_send_check ();
|
||||
|
||||
write (1, "abcdefghijklmnopqrstuvwxyz", 27);
|
||||
|
||||
#if 1
|
||||
/* Try breaking message queue system. */
|
||||
i = 0;
|
||||
while (i < 100)
|
||||
while (i < 1500)
|
||||
{
|
||||
meta_message_send_check ();
|
||||
write (1, "abcdefghijklmnopqrstuvwxyz", 27);
|
||||
if (g_random_boolean ())
|
||||
{
|
||||
int j;
|
||||
|
|
31
src/uislave/main.h
Normal file
31
src/uislave/main.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Metacity UI slave main() */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* This program 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 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_UI_MAIN_H
|
||||
#define META_UI_MAIN_H
|
||||
|
||||
void meta_ui_warning (const char *format, ...);
|
||||
|
||||
/* FIXME */
|
||||
#define _(x) x
|
||||
|
||||
|
||||
#endif
|
38
src/uislave/messagequeue.c
Normal file
38
src/uislave/messagequeue.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Metacity IPC message source for main loop */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* This program 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 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "messagequeue.h"
|
||||
|
||||
MetaMessageQueue*
|
||||
meta_message_queue_new (int fd,
|
||||
MetaMessageQueueFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
meta_message_queue_free (MetaMessageQueue *mq)
|
||||
{
|
||||
|
||||
|
||||
}
|
56
src/uislave/messagequeue.h
Normal file
56
src/uislave/messagequeue.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Metacity IPC message source for main loop */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* This program 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 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_MESSAGE_QUEUE_H
|
||||
#define META_MESSAGE_QUEUE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef METACITY_COMPILE
|
||||
#include "uislave/messages.h"
|
||||
#else
|
||||
#include "messages.h"
|
||||
#endif
|
||||
|
||||
typedef struct _MetaMessageQueue MetaMessageQueue;
|
||||
|
||||
typedef void (* MetaMessageQueueFunc) (MetaMessageQueue *mq,
|
||||
MetaMessage *message,
|
||||
gpointer data);
|
||||
|
||||
struct _MetaMessageQueue
|
||||
{
|
||||
GSource source;
|
||||
|
||||
GPollFD out_poll;
|
||||
GQueue *queue;
|
||||
GString *buf;
|
||||
GString *current_message;
|
||||
int current_required_len;
|
||||
int last_serial;
|
||||
};
|
||||
|
||||
MetaMessageQueue* meta_message_queue_new (int fd,
|
||||
MetaMessageQueueFunc func,
|
||||
gpointer data);
|
||||
void meta_message_queue_free (MetaMessageQueue *mq);
|
||||
|
||||
#endif
|
|
@ -27,6 +27,7 @@
|
|||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <config.h>
|
||||
|
||||
typedef enum
|
||||
|
@ -41,14 +42,17 @@ static ReadResult read_data (GString *str,
|
|||
|
||||
static void send_message (MetaMessage *message);
|
||||
|
||||
#define META_MESSAGE_LENGTH(real_type) \
|
||||
(G_STRUCT_OFFSET (real_type, footer) + sizeof (MetaMessageFooter))
|
||||
|
||||
void
|
||||
meta_message_send_check (void)
|
||||
{
|
||||
MetaMessageCheck check;
|
||||
|
||||
memset (&check, 0, sizeof (check));
|
||||
memset (&check, 0, META_MESSAGE_LENGTH (MetaMessageCheck));
|
||||
check.header.message_code = MetaMessageCheckCode;
|
||||
check.header.length = sizeof (check);
|
||||
check.header.length = META_MESSAGE_LENGTH (MetaMessageCheck);
|
||||
strcpy (check.metacity_version, VERSION);
|
||||
strcpy (check.host_alias, HOST_ALIAS);
|
||||
check.metacity_version[META_MESSAGE_MAX_VERSION_LEN] = '\0';
|
||||
|
@ -62,33 +66,76 @@ static int
|
|||
write_bytes (void *buf, int bytes)
|
||||
{
|
||||
const char *p;
|
||||
int left;
|
||||
|
||||
left = bytes;
|
||||
p = (char*) buf;
|
||||
while (bytes > 0)
|
||||
while (left > 0)
|
||||
{
|
||||
int written;
|
||||
|
||||
written = write (1, p, bytes);
|
||||
written = write (1, p, left);
|
||||
|
||||
if (written < 0)
|
||||
return -1;
|
||||
|
||||
bytes -= written;
|
||||
left -= written;
|
||||
p += written;
|
||||
}
|
||||
|
||||
g_assert (p == ((char*)buf) + bytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_mem (int fd, void *mem, int len)
|
||||
{
|
||||
char *p = (char*) mem;
|
||||
int i;
|
||||
char unknown = 'Z';
|
||||
char null = 'n';
|
||||
|
||||
i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
if (p[i] == '\0')
|
||||
write (fd, &null, 1);
|
||||
else if (isascii (p[i]))
|
||||
write (fd, p + i, 1);
|
||||
else
|
||||
write (fd, &unknown, 1);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
send_message (MetaMessage *message)
|
||||
{
|
||||
/* Not much point checking for errors here. We can't
|
||||
* really report them anyway.
|
||||
*/
|
||||
static int serial = 0;
|
||||
MetaMessageFooter *footer;
|
||||
|
||||
message->header.serial = serial;
|
||||
footer = META_MESSAGE_FOOTER (message);
|
||||
|
||||
footer->checksum = META_MESSAGE_CHECKSUM (message);
|
||||
++serial;
|
||||
|
||||
write_bytes (META_MESSAGE_ESCAPE, META_MESSAGE_ESCAPE_LEN);
|
||||
write_bytes (message, message->header.length);
|
||||
#if 0
|
||||
meta_ui_warning ("'");
|
||||
print_mem (2, message, message->header.length);
|
||||
meta_ui_warning ("'\n");
|
||||
#endif
|
||||
|
||||
if (write_bytes (META_MESSAGE_ESCAPE, META_MESSAGE_ESCAPE_LEN) < 0)
|
||||
meta_ui_warning ("Failed to write escape sequence: %s\n",
|
||||
g_strerror (errno));
|
||||
if (write_bytes (message, message->header.length) < 0)
|
||||
meta_ui_warning ("Failed to write message: %s\n",
|
||||
g_strerror (errno));
|
||||
}
|
||||
|
||||
static ReadResult
|
||||
|
|
|
@ -24,11 +24,14 @@
|
|||
|
||||
#include <glib.h>
|
||||
|
||||
/* This thing badly violates the KISS principle. */
|
||||
|
||||
/* This header is shared between the WM and the UI slave */
|
||||
/* Note that our IPC can be kind of lame; we trust both sides
|
||||
* of the connection, and assume that they were compiled at the
|
||||
* same time vs. the same libs on the same arch
|
||||
*/
|
||||
/* (and lo and behold, our IPC is kind of lame) */
|
||||
|
||||
/* We increment this when we change this header, so we can
|
||||
* check for mismatched UI slave and WM
|
||||
|
@ -45,11 +48,19 @@
|
|||
/* len includes nul byte which is a required part of the escape */
|
||||
#define META_MESSAGE_ESCAPE_LEN 15
|
||||
|
||||
/* This is totally useless of course. Playing around. */
|
||||
#define META_MESSAGE_CHECKSUM(msg) ((msg)->header.length | (msg)->header.serial << 16)
|
||||
#define META_MESSAGE_FOOTER(msg) ((MetaMessageFooter*) (((char*)(msg)) + ((msg)->header.length - sizeof (MetaMessageFooter))));
|
||||
|
||||
#define META_MESSAGE_MAX_SIZE (sizeof(MetaMessage));
|
||||
|
||||
#define META_MESSAGE_MAX_VERSION_LEN 15
|
||||
#define META_MESSAGE_MAX_HOST_ALIAS_LEN 50
|
||||
#define META_MESSAGE_MAX_TIP_TEXT 128
|
||||
|
||||
typedef union _MetaMessage MetaMessage;
|
||||
typedef struct _MetaMessageHeader MetaMessageHeader;
|
||||
typedef struct _MetaMessageFooter MetaMessageFooter;
|
||||
typedef struct _MetaMessageCheck MetaMessageCheck;
|
||||
typedef struct _MetaMessageShowTip MetaMessageShowTip;
|
||||
typedef struct _MetaMessageHideTip MetaMessageHideTip;
|
||||
|
@ -69,6 +80,13 @@ struct _MetaMessageHeader
|
|||
{
|
||||
MetaMessageCode message_code;
|
||||
int length;
|
||||
int serial;
|
||||
};
|
||||
|
||||
/* The footer thing was pretty much just a debug hack and could die. */
|
||||
struct _MetaMessageFooter
|
||||
{
|
||||
int checksum;
|
||||
};
|
||||
|
||||
/* just a ping to see if we have the right
|
||||
|
@ -84,6 +102,8 @@ struct _MetaMessageCheck
|
|||
char metacity_version[META_MESSAGE_MAX_VERSION_LEN + 1];
|
||||
char host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN + 1];
|
||||
int messages_version;
|
||||
|
||||
MetaMessageFooter footer;
|
||||
};
|
||||
|
||||
struct _MetaMessageShowTip
|
||||
|
@ -91,13 +111,15 @@ struct _MetaMessageShowTip
|
|||
MetaMessageHeader header;
|
||||
int root_x;
|
||||
int root_y;
|
||||
/* Then a nul-terminated string follows */
|
||||
char markup[META_MESSAGE_MAX_TIP_TEXT];
|
||||
MetaMessageFooter footer;
|
||||
};
|
||||
|
||||
struct _MetaMessageHideTip
|
||||
{
|
||||
MetaMessageHeader header;
|
||||
/* just hides the current tip */
|
||||
MetaMessageFooter footer;
|
||||
};
|
||||
|
||||
union _MetaMessage
|
||||
|
|
Loading…
Reference in a new issue