00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #define _GNU_SOURCE
00026 #define _POSIX_C_SOURCE
00027
00028 #include <config.h>
00029 #include "util.h"
00030 #include "main.h"
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <errno.h>
00036 #include <string.h>
00037 #include <X11/Xlib.h>
00038 #include <X11/Xutil.h>
00039
00040 #ifdef HAVE_BACKTRACE
00041 #include <execinfo.h>
00042 void
00043 meta_print_backtrace (void)
00044 {
00045 void *bt[500];
00046 int bt_size;
00047 int i;
00048 char **syms;
00049
00050 bt_size = backtrace (bt, 500);
00051
00052 syms = backtrace_symbols (bt, bt_size);
00053
00054 i = 0;
00055 while (i < bt_size)
00056 {
00057 meta_verbose (" %s\n", syms[i]);
00058 ++i;
00059 }
00060
00061 free (syms);
00062 }
00063 #else
00064 void
00065 meta_print_backtrace (void)
00066 {
00067 meta_verbose ("Not compiled with backtrace support\n");
00068 }
00069 #endif
00070
00071 static gboolean is_verbose = FALSE;
00072 static gboolean is_debugging = FALSE;
00073 static gboolean replace_current = FALSE;
00074 static int no_prefix = 0;
00075
00076 #ifdef WITH_VERBOSE_MODE
00077 static FILE* logfile = NULL;
00078
00079 static void
00080 ensure_logfile (void)
00081 {
00082 if (logfile == NULL && g_getenv ("METACITY_USE_LOGFILE"))
00083 {
00084 char *filename = NULL;
00085 char *tmpl;
00086 int fd;
00087 GError *err;
00088
00089 tmpl = g_strdup_printf ("metacity-%d-debug-log-XXXXXX",
00090 (int) getpid ());
00091
00092 err = NULL;
00093 fd = g_file_open_tmp (tmpl,
00094 &filename,
00095 &err);
00096
00097 g_free (tmpl);
00098
00099 if (err != NULL)
00100 {
00101 meta_warning (_("Failed to open debug log: %s\n"),
00102 err->message);
00103 g_error_free (err);
00104 return;
00105 }
00106
00107 logfile = fdopen (fd, "w");
00108
00109 if (logfile == NULL)
00110 {
00111 meta_warning (_("Failed to fdopen() log file %s: %s\n"),
00112 filename, strerror (errno));
00113 close (fd);
00114 }
00115 else
00116 {
00117 g_printerr (_("Opened log file %s\n"), filename);
00118 }
00119
00120 g_free (filename);
00121 }
00122 }
00123 #endif
00124
00125 gboolean
00126 meta_is_verbose (void)
00127 {
00128 return is_verbose;
00129 }
00130
00131 void
00132 meta_set_verbose (gboolean setting)
00133 {
00134 #ifndef WITH_VERBOSE_MODE
00135 if (setting)
00136 meta_fatal (_("Metacity was compiled without support for verbose mode\n"));
00137 #else
00138 if (setting)
00139 ensure_logfile ();
00140 #endif
00141
00142 is_verbose = setting;
00143 }
00144
00145 gboolean
00146 meta_is_debugging (void)
00147 {
00148 return is_debugging;
00149 }
00150
00151 void
00152 meta_set_debugging (gboolean setting)
00153 {
00154 #ifdef WITH_VERBOSE_MODE
00155 if (setting)
00156 ensure_logfile ();
00157 #endif
00158
00159 is_debugging = setting;
00160 }
00161
00162 gboolean
00163 meta_get_replace_current_wm (void)
00164 {
00165 return replace_current;
00166 }
00167
00168 void
00169 meta_set_replace_current_wm (gboolean setting)
00170 {
00171 replace_current = setting;
00172 }
00173
00174 char *
00175 meta_g_utf8_strndup (const gchar *src,
00176 gsize n)
00177 {
00178 const gchar *s = src;
00179 while (n && *s)
00180 {
00181 s = g_utf8_next_char (s);
00182 n--;
00183 }
00184
00185 return g_strndup (src, s - src);
00186 }
00187
00188 static int
00189 utf8_fputs (const char *str,
00190 FILE *f)
00191 {
00192 char *l;
00193 int retval;
00194
00195 l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL);
00196
00197 if (l == NULL)
00198 retval = fputs (str, f);
00199 else
00200 retval = fputs (l, f);
00201
00202 g_free (l);
00203
00204 return retval;
00205 }
00206
00207 void
00208 meta_free_gslist_and_elements (GSList *list_to_deep_free)
00209 {
00210 g_slist_foreach (list_to_deep_free,
00211 (void (*)(gpointer,gpointer))&g_free,
00212 NULL);
00213 g_slist_free (list_to_deep_free);
00214 }
00215
00216 #ifdef WITH_VERBOSE_MODE
00217 void
00218 meta_debug_spew_real (const char *format, ...)
00219 {
00220 va_list args;
00221 gchar *str;
00222 FILE *out;
00223
00224 g_return_if_fail (format != NULL);
00225
00226 if (!is_debugging)
00227 return;
00228
00229 va_start (args, format);
00230 str = g_strdup_vprintf (format, args);
00231 va_end (args);
00232
00233 out = logfile ? logfile : stderr;
00234
00235 if (no_prefix == 0)
00236 utf8_fputs (_("Window manager: "), out);
00237 utf8_fputs (str, out);
00238
00239 fflush (out);
00240
00241 g_free (str);
00242 }
00243 #endif
00244
00245 #ifdef WITH_VERBOSE_MODE
00246 void
00247 meta_verbose_real (const char *format, ...)
00248 {
00249 va_list args;
00250 gchar *str;
00251 FILE *out;
00252
00253 g_return_if_fail (format != NULL);
00254
00255 if (!is_verbose)
00256 return;
00257
00258 va_start (args, format);
00259 str = g_strdup_vprintf (format, args);
00260 va_end (args);
00261
00262 out = logfile ? logfile : stderr;
00263
00264 if (no_prefix == 0)
00265 utf8_fputs ("Window manager: ", out);
00266 utf8_fputs (str, out);
00267
00268 fflush (out);
00269
00270 g_free (str);
00271 }
00272 #endif
00273
00274 #ifdef WITH_VERBOSE_MODE
00275 static const char*
00276 topic_name (MetaDebugTopic topic)
00277 {
00278 switch (topic)
00279 {
00280 case META_DEBUG_FOCUS:
00281 return "FOCUS";
00282 case META_DEBUG_WORKAREA:
00283 return "WORKAREA";
00284 case META_DEBUG_STACK:
00285 return "STACK";
00286 case META_DEBUG_THEMES:
00287 return "THEMES";
00288 case META_DEBUG_SM:
00289 return "SM";
00290 case META_DEBUG_EVENTS:
00291 return "EVENTS";
00292 case META_DEBUG_WINDOW_STATE:
00293 return "WINDOW_STATE";
00294 case META_DEBUG_WINDOW_OPS:
00295 return "WINDOW_OPS";
00296 case META_DEBUG_PLACEMENT:
00297 return "PLACEMENT";
00298 case META_DEBUG_GEOMETRY:
00299 return "GEOMETRY";
00300 case META_DEBUG_PING:
00301 return "PING";
00302 case META_DEBUG_XINERAMA:
00303 return "XINERAMA";
00304 case META_DEBUG_KEYBINDINGS:
00305 return "KEYBINDINGS";
00306 case META_DEBUG_SYNC:
00307 return "SYNC";
00308 case META_DEBUG_ERRORS:
00309 return "ERRORS";
00310 case META_DEBUG_STARTUP:
00311 return "STARTUP";
00312 case META_DEBUG_PREFS:
00313 return "PREFS";
00314 case META_DEBUG_GROUPS:
00315 return "GROUPS";
00316 case META_DEBUG_RESIZING:
00317 return "RESIZING";
00318 case META_DEBUG_SHAPES:
00319 return "SHAPES";
00320 case META_DEBUG_COMPOSITOR:
00321 return "COMPOSITOR";
00322 case META_DEBUG_EDGE_RESISTANCE:
00323 return "EDGE_RESISTANCE";
00324 }
00325
00326 return "WM";
00327 }
00328
00329 static int sync_count = 0;
00330
00331 void
00332 meta_topic_real (MetaDebugTopic topic,
00333 const char *format,
00334 ...)
00335 {
00336 va_list args;
00337 gchar *str;
00338 FILE *out;
00339
00340 g_return_if_fail (format != NULL);
00341
00342 if (!is_verbose)
00343 return;
00344
00345 va_start (args, format);
00346 str = g_strdup_vprintf (format, args);
00347 va_end (args);
00348
00349 out = logfile ? logfile : stderr;
00350
00351 if (no_prefix == 0)
00352 fprintf (out, "%s: ", topic_name (topic));
00353
00354 if (topic == META_DEBUG_SYNC)
00355 {
00356 ++sync_count;
00357 fprintf (out, "%d: ", sync_count);
00358 }
00359
00360 utf8_fputs (str, out);
00361
00362 fflush (out);
00363
00364 g_free (str);
00365 }
00366 #endif
00367
00368 void
00369 meta_bug (const char *format, ...)
00370 {
00371 va_list args;
00372 gchar *str;
00373 FILE *out;
00374
00375 g_return_if_fail (format != NULL);
00376
00377 va_start (args, format);
00378 str = g_strdup_vprintf (format, args);
00379 va_end (args);
00380
00381 #ifdef WITH_VERBOSE_MODE
00382 out = logfile ? logfile : stderr;
00383 #else
00384 out = stderr;
00385 #endif
00386
00387 if (no_prefix == 0)
00388 utf8_fputs (_("Bug in window manager: "), out);
00389 utf8_fputs (str, out);
00390
00391 fflush (out);
00392
00393 g_free (str);
00394
00395 meta_print_backtrace ();
00396
00397
00398 abort ();
00399 }
00400
00401 void
00402 meta_warning (const char *format, ...)
00403 {
00404 va_list args;
00405 gchar *str;
00406 FILE *out;
00407
00408 g_return_if_fail (format != NULL);
00409
00410 va_start (args, format);
00411 str = g_strdup_vprintf (format, args);
00412 va_end (args);
00413
00414 #ifdef WITH_VERBOSE_MODE
00415 out = logfile ? logfile : stderr;
00416 #else
00417 out = stderr;
00418 #endif
00419
00420 if (no_prefix == 0)
00421 utf8_fputs (_("Window manager warning: "), out);
00422 utf8_fputs (str, out);
00423
00424 fflush (out);
00425
00426 g_free (str);
00427 }
00428
00429 void
00430 meta_fatal (const char *format, ...)
00431 {
00432 va_list args;
00433 gchar *str;
00434 FILE *out;
00435
00436 g_return_if_fail (format != NULL);
00437
00438 va_start (args, format);
00439 str = g_strdup_vprintf (format, args);
00440 va_end (args);
00441
00442 #ifdef WITH_VERBOSE_MODE
00443 out = logfile ? logfile : stderr;
00444 #else
00445 out = stderr;
00446 #endif
00447
00448 if (no_prefix == 0)
00449 utf8_fputs (_("Window manager error: "), out);
00450 utf8_fputs (str, out);
00451
00452 fflush (out);
00453
00454 g_free (str);
00455
00456 meta_exit (META_EXIT_ERROR);
00457 }
00458
00459 void
00460 meta_push_no_msg_prefix (void)
00461 {
00462 ++no_prefix;
00463 }
00464
00465 void
00466 meta_pop_no_msg_prefix (void)
00467 {
00468 g_return_if_fail (no_prefix > 0);
00469
00470 --no_prefix;
00471 }
00472
00473 void
00474 meta_exit (MetaExitCode code)
00475 {
00476
00477 exit (code);
00478 }
00479
00480 gint
00481 meta_unsigned_long_equal (gconstpointer v1,
00482 gconstpointer v2)
00483 {
00484 return *((const gulong*) v1) == *((const gulong*) v2);
00485 }
00486
00487 guint
00488 meta_unsigned_long_hash (gconstpointer v)
00489 {
00490 gulong val = * (const gulong *) v;
00491
00492
00493 #if GLIB_SIZEOF_LONG > 4
00494 return (guint) (val ^ (val >> 32));
00495 #else
00496 return val;
00497 #endif
00498 }
00499
00500 const char*
00501 meta_gravity_to_string (int gravity)
00502 {
00503 switch (gravity)
00504 {
00505 case NorthWestGravity:
00506 return "NorthWestGravity";
00507 break;
00508 case NorthGravity:
00509 return "NorthGravity";
00510 break;
00511 case NorthEastGravity:
00512 return "NorthEastGravity";
00513 break;
00514 case WestGravity:
00515 return "WestGravity";
00516 break;
00517 case CenterGravity:
00518 return "CenterGravity";
00519 break;
00520 case EastGravity:
00521 return "EastGravity";
00522 break;
00523 case SouthWestGravity:
00524 return "SouthWestGravity";
00525 break;
00526 case SouthGravity:
00527 return "SouthGravity";
00528 break;
00529 case SouthEastGravity:
00530 return "SouthEastGravity";
00531 break;
00532 case StaticGravity:
00533 return "StaticGravity";
00534 break;
00535 default:
00536 return "NorthWestGravity";
00537 break;
00538 }
00539 }