mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
...
This commit is contained in:
parent
c82a582a94
commit
11fde3a11a
6
po/.cvsignore
Normal file
6
po/.cvsignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Makefile.in.in
|
||||||
|
POTFILES
|
||||||
|
Makefile.in
|
||||||
|
Makefile
|
||||||
|
stamp-cat-id
|
||||||
|
cat-id-tbl.c
|
7
src/.cvsignore
Normal file
7
src/.cvsignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.libs
|
||||||
|
Makefile.in
|
||||||
|
Makefile
|
||||||
|
.deps
|
||||||
|
metacity
|
||||||
|
messagequeue.h
|
||||||
|
messagequeue.c
|
@ -18,7 +18,22 @@ BUILT_SOURCES=$(copied_sources)
|
|||||||
$(copied_sources): $(copied_sources_deps)
|
$(copied_sources): $(copied_sources_deps)
|
||||||
for I in $(copied_sources); do \
|
for I in $(copied_sources); do \
|
||||||
rm -f $$I ; \
|
rm -f $$I ; \
|
||||||
cp $(srcdir)/uislave/$$I . ; \
|
echo "/* DO NOT EDIT THIS FILE */" > $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
echo "/* DO NOT EDIT THIS FILE */" >> $$I ; \
|
||||||
|
cat $(srcdir)/uislave/$$I >> $$I ; \
|
||||||
done
|
done
|
||||||
|
|
||||||
metacity_SOURCES= \
|
metacity_SOURCES= \
|
||||||
|
@ -356,7 +356,7 @@ event_queue_callback (MetaEventQueue *queue,
|
|||||||
case ReparentNotify:
|
case ReparentNotify:
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
if (event->xconfigure.override_redirect)
|
if (window && event->xconfigure.override_redirect)
|
||||||
{
|
{
|
||||||
/* Unmanage it, override_redirect was toggled on?
|
/* Unmanage it, override_redirect was toggled on?
|
||||||
* Can this happen?
|
* Can this happen?
|
||||||
|
78
src/fixedtip.c
Normal file
78
src/fixedtip.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Metacity fixed tooltip routine */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 "fixedtip.h"
|
||||||
|
|
||||||
|
static GtkWidget *tip = NULL;
|
||||||
|
static GtkWidget *label = NULL;
|
||||||
|
|
||||||
|
static gint
|
||||||
|
expose_handler (GtkTooltips *tooltips)
|
||||||
|
{
|
||||||
|
gtk_paint_flat_box (tip->style, tip->window,
|
||||||
|
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
|
||||||
|
NULL, tip, "tooltip",
|
||||||
|
0, 0, -1, -1);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_fixed_tip_show (int root_x, int root_y,
|
||||||
|
const char *markup_text)
|
||||||
|
{
|
||||||
|
if (tip == NULL)
|
||||||
|
{
|
||||||
|
tip = gtk_window_new (GTK_WINDOW_POPUP);
|
||||||
|
gtk_widget_set_app_paintable (tip, TRUE);
|
||||||
|
gtk_window_set_policy (GTK_WINDOW (tip), FALSE, FALSE, TRUE);
|
||||||
|
gtk_widget_set_name (tip, "gtk-tooltips");
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (tip), 4);
|
||||||
|
|
||||||
|
gtk_signal_connect_object (GTK_OBJECT (tip),
|
||||||
|
"expose_event",
|
||||||
|
GTK_SIGNAL_FUNC (expose_handler),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
label = gtk_label_new (NULL);
|
||||||
|
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||||
|
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (tip), label);
|
||||||
|
|
||||||
|
gtk_signal_connect (GTK_OBJECT (tip),
|
||||||
|
"destroy",
|
||||||
|
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
|
||||||
|
&tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_uposition (tip, root_x, root_y);
|
||||||
|
gtk_label_set_markup (GTK_LABEL (label), markup_text);
|
||||||
|
|
||||||
|
gtk_widget_show (tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_fixed_tip_hide (void)
|
||||||
|
{
|
||||||
|
gtk_widget_destroy (tip);
|
||||||
|
}
|
32
src/fixedtip.h
Normal file
32
src/fixedtip.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* Metacity fixed tooltip routine */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_FIXED_TIP_H
|
||||||
|
#define META_FIXED_TIP_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
void meta_fixed_tip_show (int root_x, int root_y,
|
||||||
|
const char *markup_text);
|
||||||
|
void meta_fixed_tip_hide (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
#include "uislave.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_frame_init_info (MetaFrame *frame,
|
meta_frame_init_info (MetaFrame *frame,
|
||||||
@ -518,6 +519,12 @@ meta_frame_event (MetaFrame *frame,
|
|||||||
update_resize_se (frame);
|
update_resize_se (frame);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case META_FRAME_ACTION_NONE:
|
||||||
|
meta_ui_slave_show_tip (frame->window->screen->uislave,
|
||||||
|
frame->rect.x,
|
||||||
|
frame->rect.y,
|
||||||
|
"Hi this is a tooltip");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ static GMainLoop *meta_main_loop = NULL;
|
|||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
g_set_prgname (PACKAGE);
|
||||||
|
|
||||||
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
|
||||||
meta_set_verbose (TRUE);
|
meta_set_verbose (TRUE);
|
||||||
|
@ -35,14 +35,14 @@ struct _MetaScreen
|
|||||||
|
|
||||||
MetaThemeEngine *engine;
|
MetaThemeEngine *engine;
|
||||||
|
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
|
||||||
/* we only need one since we only draw to a single visual (that of
|
/* we only need one since we only draw to a single visual (that of
|
||||||
* root window)
|
* root window)
|
||||||
*/
|
*/
|
||||||
PangoContext *pango_context;
|
PangoContext *pango_context;
|
||||||
|
|
||||||
MetaUISlave *uislave;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||||
|
481
src/uislave.c
481
src/uislave.c
@ -27,37 +27,16 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
READ_FAILED = 0, /* FALSE */
|
|
||||||
READ_OK,
|
|
||||||
READ_EOF
|
|
||||||
} ReadResult;
|
|
||||||
|
|
||||||
static void respawn_child (MetaUISlave *uislave);
|
static void respawn_child (MetaUISlave *uislave);
|
||||||
static gboolean error_callback (GIOChannel *source,
|
static gboolean error_callback (GIOChannel *source,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
static void kill_child (MetaUISlave *uislave);
|
static void kill_child (MetaUISlave *uislave);
|
||||||
static void reset_vals (MetaUISlave *uislave);
|
static void reset_vals (MetaUISlave *uislave);
|
||||||
static ReadResult read_data (GString *str,
|
static void message_queue_func (MetaMessageQueue *mq,
|
||||||
gint fd);
|
MetaMessage* message,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
/* Message queue main loop source */
|
|
||||||
static gboolean mq_prepare (GSource *source,
|
|
||||||
gint *timeout);
|
|
||||||
static gboolean mq_check (GSource *source);
|
|
||||||
static gboolean mq_dispatch (GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer user_data);
|
|
||||||
static void mq_destroy (GSource *source);
|
|
||||||
|
|
||||||
static GSourceFuncs mq_funcs = {
|
|
||||||
mq_prepare,
|
|
||||||
mq_check,
|
|
||||||
mq_dispatch,
|
|
||||||
mq_destroy
|
|
||||||
};
|
|
||||||
|
|
||||||
MetaUISlave*
|
MetaUISlave*
|
||||||
meta_ui_slave_new (const char *display_name,
|
meta_ui_slave_new (const char *display_name,
|
||||||
@ -65,16 +44,13 @@ meta_ui_slave_new (const char *display_name,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
MetaUISlave *uislave;
|
MetaUISlave *uislave;
|
||||||
GSource *source;
|
|
||||||
|
|
||||||
source = g_source_new (&mq_funcs, sizeof (MetaUISlave));
|
uislave = g_new (MetaUISlave, 1);
|
||||||
|
|
||||||
uislave = (MetaUISlave*) source;
|
|
||||||
|
|
||||||
uislave->display_name = g_strdup (display_name);
|
uislave->display_name = g_strdup (display_name);
|
||||||
uislave->queue = g_queue_new ();
|
uislave->func = func;
|
||||||
uislave->buf = g_string_new ("");
|
uislave->data = data;
|
||||||
uislave->current_message = g_string_new ("");
|
uislave->no_respawn = FALSE;
|
||||||
|
|
||||||
reset_vals (uislave);
|
reset_vals (uislave);
|
||||||
|
|
||||||
@ -84,24 +60,21 @@ meta_ui_slave_new (const char *display_name,
|
|||||||
*/
|
*/
|
||||||
respawn_child (uislave);
|
respawn_child (uislave);
|
||||||
|
|
||||||
g_source_set_priority (source, G_PRIORITY_DEFAULT);
|
|
||||||
g_source_set_can_recurse (source, TRUE);
|
|
||||||
|
|
||||||
g_source_set_callback (source, (GSourceFunc) func, data, NULL);
|
|
||||||
|
|
||||||
g_source_attach (source, NULL);
|
|
||||||
|
|
||||||
return uislave;
|
return uislave;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_ui_slave_free (MetaUISlave *uislave)
|
meta_ui_slave_free (MetaUISlave *uislave)
|
||||||
{
|
{
|
||||||
GSource *source;
|
|
||||||
|
|
||||||
source = (GSource*) uislave;
|
meta_verbose ("Deleting UI slave for display '%s'\n",
|
||||||
|
uislave->display_name);
|
||||||
|
|
||||||
g_source_destroy (source);
|
kill_child (uislave);
|
||||||
|
|
||||||
|
g_free (uislave->display_name);
|
||||||
|
|
||||||
|
g_free (uislave);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -114,6 +87,18 @@ meta_ui_slave_disable (MetaUISlave *uislave)
|
|||||||
uislave->no_respawn = TRUE;
|
uislave->no_respawn = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_queue_func (MetaMessageQueue *mq,
|
||||||
|
MetaMessage* message,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
|
||||||
|
uislave = data;
|
||||||
|
|
||||||
|
(* uislave->func) (uislave, message, uislave->data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
respawn_child (MetaUISlave *uislave)
|
respawn_child (MetaUISlave *uislave)
|
||||||
{
|
{
|
||||||
@ -147,6 +132,7 @@ respawn_child (MetaUISlave *uislave)
|
|||||||
uislave->child_pid = child_pid;
|
uislave->child_pid = child_pid;
|
||||||
uislave->in_pipe = inpipe;
|
uislave->in_pipe = inpipe;
|
||||||
uislave->err_pipe = errpipe;
|
uislave->err_pipe = errpipe;
|
||||||
|
uislave->out_pipe = outpipe;
|
||||||
|
|
||||||
uislave->err_channel = g_io_channel_unix_new (errpipe);
|
uislave->err_channel = g_io_channel_unix_new (errpipe);
|
||||||
|
|
||||||
@ -155,10 +141,9 @@ respawn_child (MetaUISlave *uislave)
|
|||||||
error_callback,
|
error_callback,
|
||||||
uislave);
|
uislave);
|
||||||
|
|
||||||
uislave->out_poll.fd = outpipe;
|
uislave->mq = meta_message_queue_new (outpipe,
|
||||||
uislave->out_poll.events = G_IO_IN;
|
message_queue_func,
|
||||||
|
uislave);
|
||||||
g_source_add_poll ((GSource*)uislave, &uislave->out_poll);
|
|
||||||
|
|
||||||
meta_verbose ("Spawned UI slave with PID %d\n", uislave->child_pid);
|
meta_verbose ("Spawned UI slave with PID %d\n", uislave->child_pid);
|
||||||
}
|
}
|
||||||
@ -172,72 +157,6 @@ respawn_child (MetaUISlave *uislave)
|
|||||||
g_free (envp[0]);
|
g_free (envp[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
append_pending (MetaUISlave *uislave)
|
|
||||||
{
|
|
||||||
int needed;
|
|
||||||
|
|
||||||
needed = uislave->current_required_len - uislave->current_message->len;
|
|
||||||
g_assert (needed >= 0);
|
|
||||||
|
|
||||||
needed = MIN (needed, uislave->buf->len);
|
|
||||||
|
|
||||||
/* Move data from buf to current_message */
|
|
||||||
if (needed > 0)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
static gboolean
|
||||||
error_callback (GIOChannel *source,
|
error_callback (GIOChannel *source,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
@ -266,220 +185,20 @@ error_callback (GIOChannel *source,
|
|||||||
#undef BUFSIZE
|
#undef BUFSIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
mq_queue_messages (MetaUISlave *uislave)
|
|
||||||
{
|
|
||||||
if (uislave->out_poll.revents & G_IO_IN)
|
|
||||||
{
|
|
||||||
ReadResult res;
|
|
||||||
|
|
||||||
res = read_data (uislave->buf, uislave->out_poll.fd);
|
|
||||||
|
|
||||||
switch (res)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
++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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
need_more_data:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
mq_messages_pending (MetaUISlave *uislave)
|
|
||||||
{
|
|
||||||
return uislave->queue->length > 0 ||
|
|
||||||
uislave->buf->len > 0 ||
|
|
||||||
uislave->current_message->len > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
mq_prepare (GSource *source, gint *timeout)
|
|
||||||
{
|
|
||||||
MetaUISlave *uislave;
|
|
||||||
|
|
||||||
uislave = (MetaUISlave*) source;
|
|
||||||
|
|
||||||
*timeout = -1;
|
|
||||||
|
|
||||||
mq_queue_messages (uislave);
|
|
||||||
|
|
||||||
return mq_messages_pending (uislave);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
mq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaUISlave *uislave;
|
|
||||||
|
|
||||||
uislave = (MetaUISlave*) source;
|
|
||||||
|
|
||||||
if (uislave->queue->length > 0)
|
|
||||||
{
|
|
||||||
MetaUISlaveFunc func;
|
|
||||||
MetaMessage *msg;
|
|
||||||
static int count = 0;
|
|
||||||
|
|
||||||
++count;
|
|
||||||
|
|
||||||
msg = g_queue_pop_head (uislave->queue);
|
|
||||||
func = (MetaUISlaveFunc) callback;
|
|
||||||
|
|
||||||
(* func) (uislave, msg, user_data);
|
|
||||||
|
|
||||||
meta_verbose ("%d messages dispatched\n", count);
|
|
||||||
|
|
||||||
g_free (msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kill_child (MetaUISlave *uislave)
|
kill_child (MetaUISlave *uislave)
|
||||||
{
|
{
|
||||||
|
if (uislave->mq)
|
||||||
|
meta_message_queue_free (uislave->mq);
|
||||||
|
|
||||||
if (uislave->errwatch != 0)
|
if (uislave->errwatch != 0)
|
||||||
g_source_remove (uislave->errwatch);
|
g_source_remove (uislave->errwatch);
|
||||||
|
|
||||||
if (uislave->err_channel)
|
if (uislave->err_channel)
|
||||||
g_io_channel_unref (uislave->err_channel);
|
g_io_channel_unref (uislave->err_channel);
|
||||||
|
|
||||||
if (uislave->out_poll.fd >= 0)
|
if (uislave->out_pipe >= 0)
|
||||||
{
|
close (uislave->out_pipe);
|
||||||
g_source_remove_poll ((GSource*)uislave, &uislave->out_poll);
|
|
||||||
close (uislave->out_poll.fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uislave->in_pipe >= 0)
|
if (uislave->in_pipe >= 0)
|
||||||
close (uislave->in_pipe);
|
close (uislave->in_pipe);
|
||||||
@ -487,21 +206,6 @@ kill_child (MetaUISlave *uislave)
|
|||||||
if (uislave->err_pipe >= 0)
|
if (uislave->err_pipe >= 0)
|
||||||
close (uislave->err_pipe);
|
close (uislave->err_pipe);
|
||||||
|
|
||||||
while (uislave->queue->length > 0)
|
|
||||||
{
|
|
||||||
MetaMessage *msg;
|
|
||||||
|
|
||||||
msg = g_queue_pop_head (uislave->queue);
|
|
||||||
|
|
||||||
g_free (msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uislave->buf->len > 0)
|
|
||||||
g_string_truncate (uislave->buf, 0);
|
|
||||||
|
|
||||||
if (uislave->current_message->len > 0)
|
|
||||||
g_string_truncate (uislave->current_message, 0);
|
|
||||||
|
|
||||||
if (uislave->child_pid > 0)
|
if (uislave->child_pid > 0)
|
||||||
{
|
{
|
||||||
/* don't care if this fails except in verbose mode */
|
/* don't care if this fails except in verbose mode */
|
||||||
@ -520,67 +224,84 @@ kill_child (MetaUISlave *uislave)
|
|||||||
static void
|
static void
|
||||||
reset_vals (MetaUISlave *uislave)
|
reset_vals (MetaUISlave *uislave)
|
||||||
{
|
{
|
||||||
|
uislave->mq = NULL;
|
||||||
uislave->child_pid = 0;
|
uislave->child_pid = 0;
|
||||||
uislave->in_pipe = -1;
|
uislave->in_pipe = -1;
|
||||||
uislave->err_pipe = -1;
|
uislave->err_pipe = -1;
|
||||||
uislave->out_poll.fd = -1;
|
uislave->out_pipe = -1;
|
||||||
uislave->no_respawn = FALSE;
|
|
||||||
uislave->err_channel = NULL;
|
uislave->err_channel = NULL;
|
||||||
uislave->errwatch = 0;
|
uislave->errwatch = 0;
|
||||||
uislave->current_required_len = 0;
|
/* don't reset no_respawn, it's a permanent thing. */
|
||||||
uislave->last_serial = -1;
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message delivery
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_bytes (int fd, void *buf, int bytes)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
int left;
|
||||||
|
|
||||||
|
left = bytes;
|
||||||
|
p = (char*) buf;
|
||||||
|
while (left > 0)
|
||||||
|
{
|
||||||
|
int written;
|
||||||
|
|
||||||
|
written = write (fd, p, left);
|
||||||
|
|
||||||
|
if (written < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
left -= written;
|
||||||
|
p += written;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (p == ((char*)buf) + bytes);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mq_destroy (GSource *source)
|
send_message (MetaUISlave *uislave, MetaMessage *message)
|
||||||
{
|
{
|
||||||
MetaUISlave *uislave;
|
static int serial = 0;
|
||||||
|
MetaMessageFooter *footer;
|
||||||
|
|
||||||
uislave = (MetaUISlave*) source;
|
message->header.serial = serial;
|
||||||
|
footer = META_MESSAGE_FOOTER (message);
|
||||||
|
|
||||||
meta_verbose ("Deleting UI slave for display '%s'\n",
|
footer->checksum = META_MESSAGE_CHECKSUM (message);
|
||||||
uislave->display_name);
|
++serial;
|
||||||
|
|
||||||
kill_child (uislave);
|
if (write_bytes (uislave->in_pipe,
|
||||||
|
META_MESSAGE_ESCAPE, META_MESSAGE_ESCAPE_LEN) < 0)
|
||||||
g_string_free (uislave->buf, TRUE);
|
meta_warning ("Failed to write escape sequence: %s\n",
|
||||||
g_string_free (uislave->current_message, TRUE);
|
|
||||||
|
|
||||||
g_queue_free (uislave->queue);
|
|
||||||
|
|
||||||
g_free (uislave->display_name);
|
|
||||||
|
|
||||||
/* source itself is freed by glib */
|
|
||||||
}
|
|
||||||
|
|
||||||
static ReadResult
|
|
||||||
read_data (GString *str,
|
|
||||||
gint fd)
|
|
||||||
{
|
|
||||||
#define BUFSIZE 4000
|
|
||||||
gint bytes;
|
|
||||||
gchar buf[BUFSIZE];
|
|
||||||
|
|
||||||
again:
|
|
||||||
|
|
||||||
bytes = read (fd, &buf, BUFSIZE);
|
|
||||||
|
|
||||||
if (bytes == 0)
|
|
||||||
return READ_EOF;
|
|
||||||
else if (bytes > 0)
|
|
||||||
{
|
|
||||||
g_string_append_len (str, buf, bytes);
|
|
||||||
return READ_OK;
|
|
||||||
}
|
|
||||||
else if (bytes < 0 && errno == EINTR)
|
|
||||||
goto again;
|
|
||||||
else if (bytes < 0)
|
|
||||||
{
|
|
||||||
meta_warning (_("Failed to read data from UI slave: %s\n"),
|
|
||||||
g_strerror (errno));
|
g_strerror (errno));
|
||||||
|
if (write_bytes (uislave->in_pipe,
|
||||||
|
message, message->header.length) < 0)
|
||||||
|
meta_warning ("Failed to write message: %s\n",
|
||||||
|
g_strerror (errno));
|
||||||
|
}
|
||||||
|
|
||||||
return READ_FAILED;
|
void
|
||||||
}
|
meta_ui_slave_show_tip (MetaUISlave *uislave,
|
||||||
else
|
int root_x,
|
||||||
return READ_OK;
|
int root_y,
|
||||||
|
const char *markup_text)
|
||||||
|
{
|
||||||
|
MetaMessageShowTip showtip;
|
||||||
|
|
||||||
|
memset (&showtip, 0, META_MESSAGE_LENGTH (MetaMessageShowTip));
|
||||||
|
showtip.header.message_code = MetaMessageShowTipCode;
|
||||||
|
showtip.header.length = META_MESSAGE_LENGTH (MetaMessageShowTip);
|
||||||
|
|
||||||
|
showtip.root_x = root_x;
|
||||||
|
showtip.root_y = root_y;
|
||||||
|
strncpy (showtip.markup, markup_text, META_MESSAGE_MAX_TIP_LEN);
|
||||||
|
showtip.markup[META_MESSAGE_MAX_TIP_LEN] = '\0';
|
||||||
|
|
||||||
|
send_message (uislave, (MetaMessage*)&showtip);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "uislave/messages.h"
|
#include "uislave/messages.h"
|
||||||
|
#include "messagequeue.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
|
||||||
typedef void (* MetaUISlaveFunc) (MetaUISlave *uislave,
|
typedef void (* MetaUISlaveFunc) (MetaUISlave *uislave,
|
||||||
@ -32,20 +33,19 @@ typedef void (* MetaUISlaveFunc) (MetaUISlave *uislave,
|
|||||||
|
|
||||||
struct _MetaUISlave
|
struct _MetaUISlave
|
||||||
{
|
{
|
||||||
GSource source;
|
|
||||||
|
|
||||||
char *display_name;
|
char *display_name;
|
||||||
int child_pid;
|
int child_pid;
|
||||||
int in_pipe;
|
int in_pipe;
|
||||||
|
int out_pipe;
|
||||||
int err_pipe;
|
int err_pipe;
|
||||||
GPollFD out_poll;
|
|
||||||
GIOChannel *err_channel;
|
GIOChannel *err_channel;
|
||||||
unsigned int errwatch;
|
unsigned int errwatch;
|
||||||
GQueue *queue;
|
|
||||||
GString *buf;
|
MetaMessageQueue *mq;
|
||||||
GString *current_message;
|
|
||||||
int current_required_len;
|
MetaUISlaveFunc func;
|
||||||
int last_serial;
|
gpointer data;
|
||||||
|
|
||||||
/* if we determine that our available slave is hosed,
|
/* if we determine that our available slave is hosed,
|
||||||
* set this bit.
|
* set this bit.
|
||||||
*/
|
*/
|
||||||
@ -58,5 +58,9 @@ MetaUISlave* meta_ui_slave_new (const char *display_name,
|
|||||||
void meta_ui_slave_free (MetaUISlave *uislave);
|
void meta_ui_slave_free (MetaUISlave *uislave);
|
||||||
void meta_ui_slave_disable (MetaUISlave *uislave);
|
void meta_ui_slave_disable (MetaUISlave *uislave);
|
||||||
|
|
||||||
|
void meta_ui_slave_show_tip (MetaUISlave *uislave,
|
||||||
|
int root_x,
|
||||||
|
int root_y,
|
||||||
|
const char *markup_text);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
5
src/uislave/.cvsignore
Normal file
5
src/uislave/.cvsignore
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Makefile.in
|
||||||
|
Makefile
|
||||||
|
.libs
|
||||||
|
.deps
|
||||||
|
metacity-uislave
|
@ -2,6 +2,8 @@
|
|||||||
INCLUDES=@UISLAVE_CFLAGS@ -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
INCLUDES=@UISLAVE_CFLAGS@ -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
||||||
|
|
||||||
metacity_uislave_SOURCES = \
|
metacity_uislave_SOURCES = \
|
||||||
|
fixedtip.h \
|
||||||
|
fixedtip.c \
|
||||||
main.c \
|
main.c \
|
||||||
messages.c \
|
messages.c \
|
||||||
messages.h \
|
messages.h \
|
||||||
|
78
src/uislave/fixedtip.c
Normal file
78
src/uislave/fixedtip.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Metacity fixed tooltip routine */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 "fixedtip.h"
|
||||||
|
|
||||||
|
static GtkWidget *tip = NULL;
|
||||||
|
static GtkWidget *label = NULL;
|
||||||
|
|
||||||
|
static gint
|
||||||
|
expose_handler (GtkTooltips *tooltips)
|
||||||
|
{
|
||||||
|
gtk_paint_flat_box (tip->style, tip->window,
|
||||||
|
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
|
||||||
|
NULL, tip, "tooltip",
|
||||||
|
0, 0, -1, -1);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_fixed_tip_show (int root_x, int root_y,
|
||||||
|
const char *markup_text)
|
||||||
|
{
|
||||||
|
if (tip == NULL)
|
||||||
|
{
|
||||||
|
tip = gtk_window_new (GTK_WINDOW_POPUP);
|
||||||
|
gtk_widget_set_app_paintable (tip, TRUE);
|
||||||
|
gtk_window_set_policy (GTK_WINDOW (tip), FALSE, FALSE, TRUE);
|
||||||
|
gtk_widget_set_name (tip, "gtk-tooltips");
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (tip), 4);
|
||||||
|
|
||||||
|
gtk_signal_connect_object (GTK_OBJECT (tip),
|
||||||
|
"expose_event",
|
||||||
|
GTK_SIGNAL_FUNC (expose_handler),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
label = gtk_label_new (NULL);
|
||||||
|
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||||
|
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (tip), label);
|
||||||
|
|
||||||
|
gtk_signal_connect (GTK_OBJECT (tip),
|
||||||
|
"destroy",
|
||||||
|
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
|
||||||
|
&tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_uposition (tip, root_x, root_y);
|
||||||
|
gtk_label_set_markup (GTK_LABEL (label), markup_text);
|
||||||
|
|
||||||
|
gtk_widget_show (tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_fixed_tip_hide (void)
|
||||||
|
{
|
||||||
|
gtk_widget_destroy (tip);
|
||||||
|
}
|
32
src/uislave/fixedtip.h
Normal file
32
src/uislave/fixedtip.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* Metacity fixed tooltip routine */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_FIXED_TIP_H
|
||||||
|
#define META_FIXED_TIP_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
void meta_fixed_tip_show (int root_x, int root_y,
|
||||||
|
const char *markup_text);
|
||||||
|
void meta_fixed_tip_hide (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -20,6 +20,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
#include "messagequeue.h"
|
||||||
|
#include "fixedtip.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -27,6 +30,47 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
static void message_callback (MetaMessageQueue *mq,
|
||||||
|
MetaMessage *message,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
MetaMessageQueue *mq;
|
||||||
|
|
||||||
|
/* report our nature to the window manager */
|
||||||
|
meta_message_send_check ();
|
||||||
|
|
||||||
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
|
mq = meta_message_queue_new (0, message_callback, NULL);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_callback (MetaMessageQueue *mq,
|
||||||
|
MetaMessage *message,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
switch (message->header.message_code)
|
||||||
|
{
|
||||||
|
case MetaMessageShowTipCode:
|
||||||
|
meta_fixed_tip_show (message->show_tip.root_x,
|
||||||
|
message->show_tip.root_y,
|
||||||
|
message->show_tip.markup);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
meta_ui_warning ("Unhandled message code %d\n",
|
||||||
|
message->header.message_code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_ui_warning (const char *format, ...)
|
meta_ui_warning (const char *format, ...)
|
||||||
{
|
{
|
||||||
@ -44,22 +88,16 @@ meta_ui_warning (const char *format, ...)
|
|||||||
g_free (str);
|
g_free (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc, char **argv)
|
#if 0
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* report our nature to the window manager */
|
|
||||||
meta_message_send_check ();
|
|
||||||
write (1, "abcdefghijklmnopqrstuvwxyz", 27);
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* Try breaking message queue system. */
|
/* Try breaking message queue system. */
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < 1500)
|
while (i < 1500)
|
||||||
{
|
{
|
||||||
meta_message_send_check ();
|
meta_message_send_check ();
|
||||||
write (1, "abcdefghijklmnopqrstuvwxyz", 27);
|
|
||||||
if (g_random_boolean ())
|
if (g_random_boolean ())
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
@ -79,18 +117,6 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gtk_init (&argc, &argv);
|
|
||||||
|
|
||||||
gtk_main ();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,19 +20,458 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "messagequeue.h"
|
#include "messagequeue.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef METACITY_COMPILE
|
||||||
|
#include "util.h"
|
||||||
|
#else
|
||||||
|
#include "main.h"
|
||||||
|
void
|
||||||
|
meta_debug_spew (const char *format, ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_verbose (const char *format, ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_bug (const char *format, ...)
|
||||||
|
{
|
||||||
|
/* stop us in a debugger */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_warning (const char *format, ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_fatal (const char *format, ...)
|
||||||
|
{
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
#endif /* !METACITY_COMPILE */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
READ_FAILED = 0, /* FALSE */
|
||||||
|
READ_OK,
|
||||||
|
READ_EOF
|
||||||
|
} ReadResult;
|
||||||
|
|
||||||
|
static ReadResult read_data (GString *str,
|
||||||
|
gint fd);
|
||||||
|
|
||||||
|
/* Message queue main loop source */
|
||||||
|
static gboolean mq_prepare (GSource *source,
|
||||||
|
gint *timeout);
|
||||||
|
static gboolean mq_check (GSource *source);
|
||||||
|
static gboolean mq_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data);
|
||||||
|
static void mq_destroy (GSource *source);
|
||||||
|
|
||||||
|
static GSourceFuncs mq_funcs = {
|
||||||
|
mq_prepare,
|
||||||
|
mq_check,
|
||||||
|
mq_dispatch,
|
||||||
|
mq_destroy
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaMessageQueue
|
||||||
|
{
|
||||||
|
GSource source;
|
||||||
|
|
||||||
|
GPollFD out_poll;
|
||||||
|
GQueue *queue;
|
||||||
|
GString *buf;
|
||||||
|
GString *current_message;
|
||||||
|
int current_required_len;
|
||||||
|
int last_serial;
|
||||||
|
};
|
||||||
|
|
||||||
MetaMessageQueue*
|
MetaMessageQueue*
|
||||||
meta_message_queue_new (int fd,
|
meta_message_queue_new (int fd,
|
||||||
MetaMessageQueueFunc func,
|
MetaMessageQueueFunc func,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
|
MetaMessageQueue *mq;
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
source = g_source_new (&mq_funcs, sizeof (MetaMessageQueue));
|
||||||
|
|
||||||
|
mq = (MetaMessageQueue*) source;
|
||||||
|
|
||||||
|
mq->queue = g_queue_new ();
|
||||||
|
mq->buf = g_string_new ("");
|
||||||
|
mq->current_message = g_string_new ("");
|
||||||
|
mq->current_required_len = 0;
|
||||||
|
mq->last_serial = -1;
|
||||||
|
mq->out_poll.fd = fd;
|
||||||
|
mq->out_poll.events = G_IO_IN;
|
||||||
|
|
||||||
|
g_source_add_poll (source, &mq->out_poll);
|
||||||
|
|
||||||
|
g_source_set_priority (source, G_PRIORITY_DEFAULT);
|
||||||
|
g_source_set_can_recurse (source, TRUE);
|
||||||
|
|
||||||
|
g_source_set_callback (source, (GSourceFunc) func, data, NULL);
|
||||||
|
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
|
return mq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_message_queue_free (MetaMessageQueue *mq)
|
meta_message_queue_free (MetaMessageQueue *mq)
|
||||||
{
|
{
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
source = (GSource*) mq;
|
||||||
|
|
||||||
|
g_source_destroy (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_pending (MetaMessageQueue *mq)
|
||||||
|
{
|
||||||
|
int needed;
|
||||||
|
|
||||||
|
needed = mq->current_required_len - mq->current_message->len;
|
||||||
|
g_assert (needed >= 0);
|
||||||
|
|
||||||
|
needed = MIN (needed, mq->buf->len);
|
||||||
|
|
||||||
|
/* Move data from buf to current_message */
|
||||||
|
if (needed > 0)
|
||||||
|
{
|
||||||
|
meta_verbose ("Moving %d bytes from buffer to current incomplete message\n",
|
||||||
|
needed);
|
||||||
|
g_string_append_len (mq->current_message,
|
||||||
|
mq->buf->str,
|
||||||
|
needed);
|
||||||
|
g_string_erase (mq->buf,
|
||||||
|
0, needed);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (mq->current_message->len <= mq->current_required_len);
|
||||||
|
|
||||||
|
if (mq->current_required_len > 0 &&
|
||||||
|
mq->current_message->len == mq->current_required_len)
|
||||||
|
{
|
||||||
|
MetaMessage *message;
|
||||||
|
MetaMessageFooter *footer;
|
||||||
|
|
||||||
|
message = g_new (MetaMessage, 1);
|
||||||
|
|
||||||
|
memcpy (message,
|
||||||
|
mq->current_message->str, mq->current_message->len);
|
||||||
|
|
||||||
|
if (message->header.length != mq->current_required_len)
|
||||||
|
meta_bug ("Message length changed?\n");
|
||||||
|
|
||||||
|
if (message->header.serial != mq->last_serial)
|
||||||
|
meta_bug ("Message serial changed?\n");
|
||||||
|
|
||||||
|
footer = META_MESSAGE_FOOTER (message);
|
||||||
|
|
||||||
|
if (footer->checksum == META_MESSAGE_CHECKSUM (message))
|
||||||
|
{
|
||||||
|
g_queue_push_tail (mq->queue, message);
|
||||||
|
|
||||||
|
meta_verbose ("Added %d-byte message serial %d to queue\n",
|
||||||
|
mq->current_message->len, message->header.serial);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_bug ("Bad checksum %d on %d-byte message from UI slave\n",
|
||||||
|
footer->checksum, mq->current_message->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
mq->current_required_len = 0;
|
||||||
|
g_string_truncate (mq->current_message, 0);
|
||||||
|
}
|
||||||
|
else if (mq->current_required_len > 0)
|
||||||
|
{
|
||||||
|
meta_verbose ("Storing %d bytes of incomplete message\n",
|
||||||
|
mq->current_message->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mq_queue_messages (MetaMessageQueue *mq)
|
||||||
|
{
|
||||||
|
if (mq->out_poll.revents & G_IO_IN)
|
||||||
|
{
|
||||||
|
ReadResult res;
|
||||||
|
|
||||||
|
res = read_data (mq->buf, mq->out_poll.fd);
|
||||||
|
|
||||||
|
switch (res)
|
||||||
|
{
|
||||||
|
case READ_OK:
|
||||||
|
meta_verbose ("Read data from slave, %d bytes in buffer\n",
|
||||||
|
mq->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (mq->buf->len > 0)
|
||||||
|
{
|
||||||
|
if (mq->current_required_len > 0)
|
||||||
|
{
|
||||||
|
/* We had a pending message. */
|
||||||
|
append_pending (mq);
|
||||||
|
}
|
||||||
|
else if (mq->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;
|
||||||
|
|
||||||
|
g_assert (mq->current_required_len == 0);
|
||||||
|
g_assert (mq->current_message->len == 0);
|
||||||
|
|
||||||
|
meta_verbose ("Scanning for escape sequence in %d bytes\n",
|
||||||
|
mq->buf->len);
|
||||||
|
|
||||||
|
/* note that the data from the UI slave includes the nul byte */
|
||||||
|
esc = META_MESSAGE_ESCAPE;
|
||||||
|
|
||||||
|
esc_pos = -1;
|
||||||
|
p = mq->buf->str;
|
||||||
|
while (p != (mq->buf->str + mq->buf->len))
|
||||||
|
{
|
||||||
|
if (*p == *esc)
|
||||||
|
{
|
||||||
|
esc_pos = 0;
|
||||||
|
while (*p == esc[esc_pos])
|
||||||
|
{
|
||||||
|
++esc_pos;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (esc_pos == META_MESSAGE_ESCAPE_LEN ||
|
||||||
|
p == (mq->buf->str + mq->buf->len))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
esc_pos = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (esc_pos == META_MESSAGE_ESCAPE_LEN)
|
||||||
|
{
|
||||||
|
/* We found an entire escape sequence; can safely toss
|
||||||
|
* out the entire buffer before it
|
||||||
|
*/
|
||||||
|
int ignored;
|
||||||
|
|
||||||
|
g_assert (esc[META_MESSAGE_ESCAPE_LEN-1] == *(p-1));
|
||||||
|
|
||||||
|
ignored = p - mq->buf->str;
|
||||||
|
ignored -= META_MESSAGE_ESCAPE_LEN;
|
||||||
|
|
||||||
|
g_assert (ignored >= 0);
|
||||||
|
g_assert (mq->buf->str[ignored] == esc[0]);
|
||||||
|
|
||||||
|
if (ignored > 0)
|
||||||
|
{
|
||||||
|
g_string_erase (mq->buf, 0, ignored);
|
||||||
|
meta_verbose ("Ignoring %d bytes before escape, new buffer len %d\n",
|
||||||
|
ignored, mq->buf->len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert (p == (mq->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",
|
||||||
|
mq->buf->len);
|
||||||
|
g_string_truncate (mq->buf, 0);
|
||||||
|
goto need_more_data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_verbose ("Buffer ends with partial escape sequence\n");
|
||||||
|
goto need_more_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (strcmp (mq->buf->str, META_MESSAGE_ESCAPE) == 0);
|
||||||
|
|
||||||
|
if (mq->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 (mq->buf, 0, META_MESSAGE_ESCAPE_LEN);
|
||||||
|
meta_verbose ("Stripped escape off front of buffer, new buffer len %d\n",
|
||||||
|
mq->buf->len);
|
||||||
|
|
||||||
|
g_assert (mq->buf->len >= sizeof (MetaMessageHeader));
|
||||||
|
|
||||||
|
memcpy (&header, mq->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 != mq->last_serial + 1)
|
||||||
|
meta_bug ("Wrong message serial number %d from UI slave!\n", header.serial);
|
||||||
|
|
||||||
|
mq->last_serial = header.serial;
|
||||||
|
mq->current_required_len = header.length;
|
||||||
|
|
||||||
|
append_pending (mq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto need_more_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
need_more_data:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_messages_pending (MetaMessageQueue *mq)
|
||||||
|
{
|
||||||
|
return mq->queue->length > 0 ||
|
||||||
|
mq->buf->len > 0 ||
|
||||||
|
mq->current_message->len > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_prepare (GSource *source, gint *timeout)
|
||||||
|
{
|
||||||
|
MetaMessageQueue *mq;
|
||||||
|
|
||||||
|
mq = (MetaMessageQueue*) source;
|
||||||
|
|
||||||
|
*timeout = -1;
|
||||||
|
|
||||||
|
mq_queue_messages (mq);
|
||||||
|
|
||||||
|
return mq_messages_pending (mq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_check (GSource *source)
|
||||||
|
{
|
||||||
|
MetaMessageQueue *mq;
|
||||||
|
|
||||||
|
mq = (MetaMessageQueue*) source;
|
||||||
|
|
||||||
|
mq_queue_messages (mq);
|
||||||
|
mq->out_poll.revents = 0;
|
||||||
|
|
||||||
|
return mq_messages_pending (mq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaMessageQueue *mq;
|
||||||
|
|
||||||
|
mq = (MetaMessageQueue*) source;
|
||||||
|
|
||||||
|
if (mq->queue->length > 0)
|
||||||
|
{
|
||||||
|
MetaMessageQueueFunc func;
|
||||||
|
MetaMessage *msg;
|
||||||
|
static int count = 0;
|
||||||
|
|
||||||
|
++count;
|
||||||
|
|
||||||
|
msg = g_queue_pop_head (mq->queue);
|
||||||
|
func = (MetaMessageQueueFunc) callback;
|
||||||
|
|
||||||
|
(* func) (mq, msg, user_data);
|
||||||
|
|
||||||
|
meta_verbose ("%d messages dispatched\n", count);
|
||||||
|
|
||||||
|
g_free (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mq_destroy (GSource *source)
|
||||||
|
{
|
||||||
|
MetaMessageQueue *mq;
|
||||||
|
|
||||||
|
mq = (MetaMessageQueue*) source;
|
||||||
|
|
||||||
|
while (mq->queue->length > 0)
|
||||||
|
{
|
||||||
|
MetaMessage *msg;
|
||||||
|
|
||||||
|
msg = g_queue_pop_head (mq->queue);
|
||||||
|
|
||||||
|
g_free (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_free (mq->buf, TRUE);
|
||||||
|
g_string_free (mq->current_message, TRUE);
|
||||||
|
|
||||||
|
g_queue_free (mq->queue);
|
||||||
|
|
||||||
|
/* source itself is freed by glib */
|
||||||
|
}
|
||||||
|
|
||||||
|
static ReadResult
|
||||||
|
read_data (GString *str,
|
||||||
|
gint fd)
|
||||||
|
{
|
||||||
|
#define BUFSIZE 1024
|
||||||
|
gint bytes;
|
||||||
|
gchar buf[BUFSIZE];
|
||||||
|
|
||||||
|
again:
|
||||||
|
|
||||||
|
bytes = read (fd, &buf, BUFSIZE);
|
||||||
|
|
||||||
|
if (bytes == 0)
|
||||||
|
return READ_EOF;
|
||||||
|
else if (bytes > 0)
|
||||||
|
{
|
||||||
|
g_string_append_len (str, buf, bytes);
|
||||||
|
return READ_OK;
|
||||||
|
}
|
||||||
|
else if (bytes < 0 && errno == EINTR)
|
||||||
|
goto again;
|
||||||
|
else if (bytes < 0)
|
||||||
|
{
|
||||||
|
meta_warning (_("Failed to read data from UI slave: %s\n"),
|
||||||
|
g_strerror (errno));
|
||||||
|
|
||||||
|
return READ_FAILED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return READ_OK;
|
||||||
}
|
}
|
||||||
|
@ -36,18 +36,6 @@ typedef void (* MetaMessageQueueFunc) (MetaMessageQueue *mq,
|
|||||||
MetaMessage *message,
|
MetaMessage *message,
|
||||||
gpointer data);
|
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,
|
MetaMessageQueue* meta_message_queue_new (int fd,
|
||||||
MetaMessageQueueFunc func,
|
MetaMessageQueueFunc func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
@ -42,9 +42,6 @@ static ReadResult read_data (GString *str,
|
|||||||
|
|
||||||
static void send_message (MetaMessage *message);
|
static void send_message (MetaMessage *message);
|
||||||
|
|
||||||
#define META_MESSAGE_LENGTH(real_type) \
|
|
||||||
(G_STRUCT_OFFSET (real_type, footer) + sizeof (MetaMessageFooter))
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_message_send_check (void)
|
meta_message_send_check (void)
|
||||||
{
|
{
|
||||||
@ -53,10 +50,13 @@ meta_message_send_check (void)
|
|||||||
memset (&check, 0, META_MESSAGE_LENGTH (MetaMessageCheck));
|
memset (&check, 0, META_MESSAGE_LENGTH (MetaMessageCheck));
|
||||||
check.header.message_code = MetaMessageCheckCode;
|
check.header.message_code = MetaMessageCheckCode;
|
||||||
check.header.length = META_MESSAGE_LENGTH (MetaMessageCheck);
|
check.header.length = META_MESSAGE_LENGTH (MetaMessageCheck);
|
||||||
strcpy (check.metacity_version, VERSION);
|
|
||||||
strcpy (check.host_alias, HOST_ALIAS);
|
strncpy (check.metacity_version, VERSION, META_MESSAGE_MAX_VERSION_LEN);
|
||||||
check.metacity_version[META_MESSAGE_MAX_VERSION_LEN] = '\0';
|
check.metacity_version[META_MESSAGE_MAX_VERSION_LEN] = '\0';
|
||||||
|
|
||||||
|
strncpy (check.host_alias, HOST_ALIAS, META_MESSAGE_MAX_HOST_ALIAS_LEN);
|
||||||
check.host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN] = '\0';
|
check.host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN] = '\0';
|
||||||
|
|
||||||
check.messages_version = META_MESSAGES_VERSION;
|
check.messages_version = META_MESSAGES_VERSION;
|
||||||
|
|
||||||
send_message ((MetaMessage*)&check);
|
send_message ((MetaMessage*)&check);
|
||||||
|
@ -51,12 +51,14 @@
|
|||||||
/* This is totally useless of course. Playing around. */
|
/* This is totally useless of course. Playing around. */
|
||||||
#define META_MESSAGE_CHECKSUM(msg) ((msg)->header.length | (msg)->header.serial << 16)
|
#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_FOOTER(msg) ((MetaMessageFooter*) (((char*)(msg)) + ((msg)->header.length - sizeof (MetaMessageFooter))));
|
||||||
|
#define META_MESSAGE_LENGTH(real_type) \
|
||||||
|
(G_STRUCT_OFFSET (real_type, footer) + sizeof (MetaMessageFooter))
|
||||||
|
|
||||||
#define META_MESSAGE_MAX_SIZE (sizeof(MetaMessage));
|
#define META_MESSAGE_MAX_SIZE (sizeof(MetaMessage));
|
||||||
|
|
||||||
#define META_MESSAGE_MAX_VERSION_LEN 15
|
#define META_MESSAGE_MAX_VERSION_LEN 15
|
||||||
#define META_MESSAGE_MAX_HOST_ALIAS_LEN 50
|
#define META_MESSAGE_MAX_HOST_ALIAS_LEN 50
|
||||||
#define META_MESSAGE_MAX_TIP_TEXT 128
|
#define META_MESSAGE_MAX_TIP_LEN 128
|
||||||
|
|
||||||
typedef union _MetaMessage MetaMessage;
|
typedef union _MetaMessage MetaMessage;
|
||||||
typedef struct _MetaMessageHeader MetaMessageHeader;
|
typedef struct _MetaMessageHeader MetaMessageHeader;
|
||||||
@ -111,7 +113,7 @@ struct _MetaMessageShowTip
|
|||||||
MetaMessageHeader header;
|
MetaMessageHeader header;
|
||||||
int root_x;
|
int root_x;
|
||||||
int root_y;
|
int root_y;
|
||||||
char markup[META_MESSAGE_MAX_TIP_TEXT];
|
char markup[META_MESSAGE_MAX_TIP_LEN + 1];
|
||||||
MetaMessageFooter footer;
|
MetaMessageFooter footer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user