mutter/src/util.c

432 lines
7.6 KiB
C
Raw Normal View History

2001-05-30 11:36:31 -04:00
/* Metacity utilities */
/*
* 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 <config.h>
2001-05-30 11:36:31 -04:00
#include "util.h"
#include "main.h"
#include <stdio.h>
2001-05-30 23:30:58 -04:00
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
2001-05-30 11:36:31 -04:00
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
void
meta_print_backtrace (void)
{
void *bt[500];
int bt_size;
int i;
char **syms;
bt_size = backtrace (bt, 500);
syms = backtrace_symbols (bt, bt_size);
i = 0;
while (i < bt_size)
{
meta_verbose (" %s\n", syms[i]);
++i;
}
free (syms);
}
#else
void
meta_print_backtrace (void)
{
meta_verbose ("Not compiled with backtrace support\n");
}
#endif
2001-05-31 02:42:58 -04:00
static gboolean is_verbose = FALSE;
static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE;
2001-06-10 15:23:28 -04:00
static int no_prefix = 0;
2001-06-11 01:47:51 -04:00
static FILE* logfile = NULL;
static void
ensure_logfile (void)
{
if (logfile == NULL && g_getenv ("METACITY_USE_LOGFILE"))
2001-06-11 01:47:51 -04:00
{
char *filename = NULL;
char *tmpl;
int fd;
GError *err;
2001-06-11 01:47:51 -04:00
tmpl = g_strdup_printf ("metacity-%d-debug-log-XXXXXX",
(int) getpid ());
err = NULL;
fd = g_file_open_tmp (tmpl,
&filename,
&err);
2001-06-11 01:47:51 -04:00
g_free (tmpl);
if (err != NULL)
{
meta_warning (_("Failed to open debug log: %s\n"),
err->message);
g_error_free (err);
return;
}
logfile = fdopen (fd, "w");
2001-06-11 01:47:51 -04:00
if (logfile == NULL)
{
meta_warning (_("Failed to fdopen() log file %s: %s\n"),
filename, strerror (errno));
close (fd);
}
2001-06-11 01:47:51 -04:00
else
{
g_print (_("Opened log file %s\n"), filename);
}
2001-06-11 01:47:51 -04:00
g_free (filename);
2001-06-11 01:47:51 -04:00
}
}
2001-05-30 11:36:31 -04:00
gboolean
meta_is_verbose (void)
{
return is_verbose;
}
void
meta_set_verbose (gboolean setting)
{
2001-06-11 01:47:51 -04:00
if (setting)
ensure_logfile ();
2001-05-30 11:36:31 -04:00
is_verbose = setting;
}
2001-05-31 02:42:58 -04:00
gboolean
meta_is_debugging (void)
{
return is_debugging;
}
void
meta_set_debugging (gboolean setting)
{
2001-06-11 01:47:51 -04:00
if (setting)
ensure_logfile ();
2001-05-31 02:42:58 -04:00
is_debugging = setting;
}
gboolean
meta_get_replace_current_wm (void)
{
return replace_current;
}
void
meta_set_replace_current_wm (gboolean setting)
{
replace_current = setting;
}
static int
utf8_fputs (const char *str,
FILE *f)
{
char *l;
lengthen to 15 seconds 2002-11-30 Havoc Pennington <hp@pobox.com> * src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds * src/util.c (utf8_fputs): hmm, return a value * src/screen.c (meta_screen_apply_startup_properties): new function to apply initial workspace based on startup sequence. * src/window.c (meta_window_new): load _NET_STARTUP_ID (meta_window_get_startup_id): new function * src/window-props.c (meta_display_init_window_prop_hooks): add hooks for _NET_STARTUP_ID * src/display.c (event_callback): send property events to groups. * src/xprops.c (meta_prop_get_values): make a type of INVALID mean to ignore that property (don't fetch its value). * src/group.c (meta_group_property_notify): new function * src/screen.c (set_supported_hint): support _NET_STARTUP_ID * src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms we initialize * src/group-private.h: private header shared between group-props.c, group.c * src/group-props.h, src/group-props.c: new files to contain functions for retrieving group properties * src/window.c (meta_window_same_application): change this a bit to work with new definition of group * src/group.c (meta_window_get_group): always create a group for every window, using the window's own ID as group leader if required. * src/window.c (update_wm_hints): handle changes to group leader * src/group.c (meta_window_group_leader_changed): new function * src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH, not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen. * src/screen.c (startup_sequence_timeout): when timing out a startup sequence, send a remove message, don't just time it out locally.
2002-11-30 22:58:04 -05:00
int retval;
l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL);
if (l == NULL)
lengthen to 15 seconds 2002-11-30 Havoc Pennington <hp@pobox.com> * src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds * src/util.c (utf8_fputs): hmm, return a value * src/screen.c (meta_screen_apply_startup_properties): new function to apply initial workspace based on startup sequence. * src/window.c (meta_window_new): load _NET_STARTUP_ID (meta_window_get_startup_id): new function * src/window-props.c (meta_display_init_window_prop_hooks): add hooks for _NET_STARTUP_ID * src/display.c (event_callback): send property events to groups. * src/xprops.c (meta_prop_get_values): make a type of INVALID mean to ignore that property (don't fetch its value). * src/group.c (meta_group_property_notify): new function * src/screen.c (set_supported_hint): support _NET_STARTUP_ID * src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms we initialize * src/group-private.h: private header shared between group-props.c, group.c * src/group-props.h, src/group-props.c: new files to contain functions for retrieving group properties * src/window.c (meta_window_same_application): change this a bit to work with new definition of group * src/group.c (meta_window_get_group): always create a group for every window, using the window's own ID as group leader if required. * src/window.c (update_wm_hints): handle changes to group leader * src/group.c (meta_window_group_leader_changed): new function * src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH, not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen. * src/screen.c (startup_sequence_timeout): when timing out a startup sequence, send a remove message, don't just time it out locally.
2002-11-30 22:58:04 -05:00
retval = fputs (str, f); /* just print it anyway, better than nothing */
else
lengthen to 15 seconds 2002-11-30 Havoc Pennington <hp@pobox.com> * src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds * src/util.c (utf8_fputs): hmm, return a value * src/screen.c (meta_screen_apply_startup_properties): new function to apply initial workspace based on startup sequence. * src/window.c (meta_window_new): load _NET_STARTUP_ID (meta_window_get_startup_id): new function * src/window-props.c (meta_display_init_window_prop_hooks): add hooks for _NET_STARTUP_ID * src/display.c (event_callback): send property events to groups. * src/xprops.c (meta_prop_get_values): make a type of INVALID mean to ignore that property (don't fetch its value). * src/group.c (meta_group_property_notify): new function * src/screen.c (set_supported_hint): support _NET_STARTUP_ID * src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms we initialize * src/group-private.h: private header shared between group-props.c, group.c * src/group-props.h, src/group-props.c: new files to contain functions for retrieving group properties * src/window.c (meta_window_same_application): change this a bit to work with new definition of group * src/group.c (meta_window_get_group): always create a group for every window, using the window's own ID as group leader if required. * src/window.c (update_wm_hints): handle changes to group leader * src/group.c (meta_window_group_leader_changed): new function * src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH, not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen. * src/screen.c (startup_sequence_timeout): when timing out a startup sequence, send a remove message, don't just time it out locally.
2002-11-30 22:58:04 -05:00
retval = fputs (l, f);
g_free (l);
lengthen to 15 seconds 2002-11-30 Havoc Pennington <hp@pobox.com> * src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds * src/util.c (utf8_fputs): hmm, return a value * src/screen.c (meta_screen_apply_startup_properties): new function to apply initial workspace based on startup sequence. * src/window.c (meta_window_new): load _NET_STARTUP_ID (meta_window_get_startup_id): new function * src/window-props.c (meta_display_init_window_prop_hooks): add hooks for _NET_STARTUP_ID * src/display.c (event_callback): send property events to groups. * src/xprops.c (meta_prop_get_values): make a type of INVALID mean to ignore that property (don't fetch its value). * src/group.c (meta_group_property_notify): new function * src/screen.c (set_supported_hint): support _NET_STARTUP_ID * src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms we initialize * src/group-private.h: private header shared between group-props.c, group.c * src/group-props.h, src/group-props.c: new files to contain functions for retrieving group properties * src/window.c (meta_window_same_application): change this a bit to work with new definition of group * src/group.c (meta_window_get_group): always create a group for every window, using the window's own ID as group leader if required. * src/window.c (update_wm_hints): handle changes to group leader * src/group.c (meta_window_group_leader_changed): new function * src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH, not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen. * src/screen.c (startup_sequence_timeout): when timing out a startup sequence, send a remove message, don't just time it out locally.
2002-11-30 22:58:04 -05:00
return retval;
}
2001-05-30 11:36:31 -04:00
void
meta_debug_spew (const char *format, ...)
{
va_list args;
gchar *str;
2001-06-11 01:47:51 -04:00
FILE *out;
2001-05-30 11:36:31 -04:00
g_return_if_fail (format != NULL);
2001-05-31 02:42:58 -04:00
if (!is_debugging)
2001-05-30 11:36:31 -04:00
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
2001-06-11 01:47:51 -04:00
out = logfile ? logfile : stderr;
2001-06-10 15:23:28 -04:00
if (no_prefix == 0)
utf8_fputs (_("Window manager: "), out);
utf8_fputs (str, out);
2001-06-21 02:08:35 -04:00
fflush (out);
2001-05-30 11:36:31 -04:00
g_free (str);
}
void
meta_verbose (const char *format, ...)
{
va_list args;
gchar *str;
2001-06-11 01:47:51 -04:00
FILE *out;
2001-05-30 11:36:31 -04:00
g_return_if_fail (format != NULL);
if (!is_verbose)
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
2001-06-11 01:47:51 -04:00
out = logfile ? logfile : stderr;
2001-06-10 15:23:28 -04:00
if (no_prefix == 0)
utf8_fputs ("Window manager: ", out);
utf8_fputs (str, out);
2001-06-21 02:08:35 -04:00
fflush (out);
2001-05-30 11:36:31 -04:00
g_free (str);
}
static const char*
topic_name (MetaDebugTopic topic)
{
switch (topic)
{
case META_DEBUG_FOCUS:
return "FOCUS";
case META_DEBUG_WORKAREA:
return "WORKAREA";
case META_DEBUG_STACK:
return "STACK";
case META_DEBUG_THEMES:
return "THEMES";
case META_DEBUG_SM:
return "SM";
case META_DEBUG_EVENTS:
return "EVENTS";
case META_DEBUG_WINDOW_STATE:
return "WINDOW_STATE";
case META_DEBUG_WINDOW_OPS:
return "WINDOW_OPS";
case META_DEBUG_PLACEMENT:
return "PLACEMENT";
case META_DEBUG_GEOMETRY:
return "GEOMETRY";
case META_DEBUG_PING:
return "PING";
case META_DEBUG_XINERAMA:
return "XINERAMA";
case META_DEBUG_KEYBINDINGS:
return "KEYBINDINGS";
case META_DEBUG_SYNC:
return "SYNC";
case META_DEBUG_ERRORS:
return "ERRORS";
case META_DEBUG_STARTUP:
return "STARTUP";
case META_DEBUG_PREFS:
return "PREFS";
lengthen to 15 seconds 2002-11-30 Havoc Pennington <hp@pobox.com> * src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds * src/util.c (utf8_fputs): hmm, return a value * src/screen.c (meta_screen_apply_startup_properties): new function to apply initial workspace based on startup sequence. * src/window.c (meta_window_new): load _NET_STARTUP_ID (meta_window_get_startup_id): new function * src/window-props.c (meta_display_init_window_prop_hooks): add hooks for _NET_STARTUP_ID * src/display.c (event_callback): send property events to groups. * src/xprops.c (meta_prop_get_values): make a type of INVALID mean to ignore that property (don't fetch its value). * src/group.c (meta_group_property_notify): new function * src/screen.c (set_supported_hint): support _NET_STARTUP_ID * src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms we initialize * src/group-private.h: private header shared between group-props.c, group.c * src/group-props.h, src/group-props.c: new files to contain functions for retrieving group properties * src/window.c (meta_window_same_application): change this a bit to work with new definition of group * src/group.c (meta_window_get_group): always create a group for every window, using the window's own ID as group leader if required. * src/window.c (update_wm_hints): handle changes to group leader * src/group.c (meta_window_group_leader_changed): new function * src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH, not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen. * src/screen.c (startup_sequence_timeout): when timing out a startup sequence, send a remove message, don't just time it out locally.
2002-11-30 22:58:04 -05:00
case META_DEBUG_GROUPS:
return "GROUPS";
}
return "Window manager";
}
static int sync_count = 0;
void
meta_topic (MetaDebugTopic topic,
const char *format,
...)
{
va_list args;
gchar *str;
FILE *out;
g_return_if_fail (format != NULL);
if (!is_verbose)
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
out = logfile ? logfile : stderr;
if (no_prefix == 0)
fprintf (out, "%s: ", topic_name (topic));
if (topic == META_DEBUG_SYNC)
{
++sync_count;
fprintf (out, "%d: ", sync_count);
}
utf8_fputs (str, out);
fflush (out);
g_free (str);
}
2001-05-30 23:30:58 -04:00
void
meta_bug (const char *format, ...)
{
va_list args;
gchar *str;
2001-06-11 01:47:51 -04:00
FILE *out;
2001-05-30 23:30:58 -04:00
g_return_if_fail (format != NULL);
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
2001-06-11 01:47:51 -04:00
out = logfile ? logfile : stderr;
2001-06-10 15:23:28 -04:00
if (no_prefix == 0)
utf8_fputs (_("Bug in window manager: "), out);
utf8_fputs (str, out);
2001-06-21 02:08:35 -04:00
fflush (out);
2001-05-30 23:30:58 -04:00
g_free (str);
meta_print_backtrace ();
2001-05-30 23:30:58 -04:00
/* stop us in a debugger */
abort ();
}
2001-05-30 11:36:31 -04:00
void
meta_warning (const char *format, ...)
{
va_list args;
gchar *str;
2001-06-11 01:47:51 -04:00
FILE *out;
2001-05-30 11:36:31 -04:00
g_return_if_fail (format != NULL);
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
2001-06-11 01:47:51 -04:00
out = logfile ? logfile : stderr;
2001-06-10 15:23:28 -04:00
if (no_prefix == 0)
utf8_fputs (_("Window manager warning: "), out);
utf8_fputs (str, out);
fflush (out);
2001-05-30 11:36:31 -04:00
g_free (str);
}
void
meta_fatal (const char *format, ...)
{
va_list args;
gchar *str;
2001-06-11 01:47:51 -04:00
FILE *out;
2001-05-30 11:36:31 -04:00
g_return_if_fail (format != NULL);
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
2001-06-11 01:47:51 -04:00
out = logfile ? logfile : stderr;
2001-06-10 15:23:28 -04:00
if (no_prefix == 0)
utf8_fputs (_("Window manager error: "), out);
utf8_fputs (str, out);
2001-06-21 02:08:35 -04:00
fflush (out);
2001-05-30 11:36:31 -04:00
g_free (str);
meta_exit (META_EXIT_ERROR);
}
2001-06-10 15:23:28 -04:00
void
meta_push_no_msg_prefix (void)
{
++no_prefix;
}
void
meta_pop_no_msg_prefix (void)
{
g_return_if_fail (no_prefix > 0);
--no_prefix;
}
void
meta_exit (MetaExitCode code)
{
exit (code);
}
gint
meta_unsigned_long_equal (gconstpointer v1,
gconstpointer v2)
{
return *((const gulong*) v1) == *((const gulong*) v2);
}
guint
meta_unsigned_long_hash (gconstpointer v)
{
gulong val = * (const gulong *) v;
/* I'm not sure this works so well. */
#if G_SIZEOF_LONG > 4
return (guint) (val ^ (val >> 32));
#else
return val;
#endif
}