Commit 11fde3a1 authored by rhp's avatar rhp
Browse files

...

parent c82a582a
Makefile.in.in
POTFILES
Makefile.in
Makefile
stamp-cat-id
cat-id-tbl.c
.libs
Makefile.in
Makefile
.deps
metacity
messagequeue.h
messagequeue.c
......@@ -18,7 +18,22 @@ BUILT_SOURCES=$(copied_sources)
$(copied_sources): $(copied_sources_deps)
for I in $(copied_sources); do \
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
metacity_SOURCES= \
......
......@@ -356,7 +356,7 @@ event_queue_callback (MetaEventQueue *queue,
case ReparentNotify:
break;
case ConfigureNotify:
if (event->xconfigure.override_redirect)
if (window && event->xconfigure.override_redirect)
{
/* Unmanage it, override_redirect was toggled on?
* Can this happen?
......
/* 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);
}
/* 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 "errors.h"
#include "uislave.h"
static void
meta_frame_init_info (MetaFrame *frame,
......@@ -517,7 +518,13 @@ meta_frame_event (MetaFrame *frame,
case META_FRAME_ACTION_RESIZING_SE:
update_resize_se (frame);
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:
break;
}
......
......@@ -32,8 +32,10 @@ static GMainLoop *meta_main_loop = NULL;
int
main (int argc, char **argv)
{
g_set_prgname (PACKAGE);
meta_main_loop = g_main_loop_new (NULL, FALSE);
meta_set_verbose (TRUE);
meta_set_debugging (TRUE);
meta_set_syncing (g_getenv ("METACITY_SYNC") != NULL);
......
......@@ -34,6 +34,8 @@ struct _MetaScreen
Window xroot;
MetaThemeEngine *engine;
MetaUISlave *uislave;
/*< private >*/
......@@ -41,8 +43,6 @@ struct _MetaScreen
* root window)
*/
PangoContext *pango_context;
MetaUISlave *uislave;
};
MetaScreen* meta_screen_new (MetaDisplay *display,
......
......@@ -27,37 +27,16 @@
#include <signal.h>
#include <fcntl.h>
typedef enum
{
READ_FAILED = 0, /* FALSE */
READ_OK,
READ_EOF
} ReadResult;
static void respawn_child (MetaUISlave *uislave);
static gboolean error_callback (GIOChannel *source,
GIOCondition condition,
gpointer data);
static void kill_child (MetaUISlave *uislave);
static void reset_vals (MetaUISlave *uislave);
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
};
static void message_queue_func (MetaMessageQueue *mq,
MetaMessage* message,
gpointer data);
MetaUISlave*
meta_ui_slave_new (const char *display_name,
......@@ -65,16 +44,13 @@ meta_ui_slave_new (const char *display_name,
gpointer data)
{
MetaUISlave *uislave;
GSource *source;
source = g_source_new (&mq_funcs, sizeof (MetaUISlave));
uislave = (MetaUISlave*) source;
uislave = g_new (MetaUISlave, 1);
uislave->display_name = g_strdup (display_name);
uislave->queue = g_queue_new ();
uislave->buf = g_string_new ("");
uislave->current_message = g_string_new ("");
uislave->func = func;
uislave->data = data;
uislave->no_respawn = FALSE;
reset_vals (uislave);
......@@ -82,14 +58,7 @@ meta_ui_slave_new (const char *display_name,
* if uislave->child_pids == 0, and metacity just runs
* with no UI features other than window borders.
*/
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);
respawn_child (uislave);
return uislave;
}
......@@ -97,11 +66,15 @@ meta_ui_slave_new (const char *display_name,
void
meta_ui_slave_free (MetaUISlave *uislave)
{
GSource *source;
source = (GSource*) uislave;
meta_verbose ("Deleting UI slave for display '%s'\n",
uislave->display_name);
kill_child (uislave);
g_source_destroy (source);
g_free (uislave->display_name);
g_free (uislave);
}
void
......@@ -114,6 +87,18 @@ meta_ui_slave_disable (MetaUISlave *uislave)
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
respawn_child (MetaUISlave *uislave)
{
......@@ -147,6 +132,7 @@ respawn_child (MetaUISlave *uislave)
uislave->child_pid = child_pid;
uislave->in_pipe = inpipe;
uislave->err_pipe = errpipe;
uislave->out_pipe = outpipe;
uislave->err_channel = g_io_channel_unix_new (errpipe);
......@@ -154,11 +140,10 @@ respawn_child (MetaUISlave *uislave)
G_IO_IN,
error_callback,
uislave);
uislave->out_poll.fd = outpipe;
uislave->out_poll.events = G_IO_IN;
g_source_add_poll ((GSource*)uislave, &uislave->out_poll);
uislave->mq = meta_message_queue_new (outpipe,
message_queue_func,
uislave);
meta_verbose ("Spawned UI slave with PID %d\n", uislave->child_pid);
}
......@@ -172,72 +157,6 @@ respawn_child (MetaUISlave *uislave)
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
error_callback (GIOChannel *source,
GIOCondition condition,
......@@ -266,220 +185,20 @@ error_callback (GIOChannel *source,
#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
kill_child (MetaUISlave *uislave)
{
if (uislave->mq)
meta_message_queue_free (uislave->mq);