Blame gtk/gtkmain.c

Packit 98cdb6
/* GTK - The GIMP Toolkit
Packit 98cdb6
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Lesser General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
Packit 98cdb6
 * Lesser General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Lesser General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
Packit 98cdb6
 * file for a list of people on the GTK+ Team.  See the ChangeLog
Packit 98cdb6
 * files for a list of changes.  These files are distributed with
Packit 98cdb6
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
Packit 98cdb6
#include "gtkmain.h"
Packit 98cdb6
Packit 98cdb6
#include <glib.h>
Packit 98cdb6
#include "gdkconfig.h"
Packit 98cdb6
Packit 98cdb6
#include <locale.h>
Packit 98cdb6
Packit 98cdb6
#include <stdio.h>
Packit 98cdb6
#include <stdlib.h>
Packit 98cdb6
#include <string.h>
Packit 98cdb6
#ifdef HAVE_UNISTD_H
Packit 98cdb6
#include <unistd.h>
Packit 98cdb6
#endif
Packit 98cdb6
#include <sys/types.h>		/* For uid_t, gid_t */
Packit 98cdb6
Packit 98cdb6
#ifdef G_OS_WIN32
Packit 98cdb6
#define STRICT
Packit 98cdb6
#include <windows.h>
Packit 98cdb6
#undef STRICT
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
#include "gtkintl.h"
Packit 98cdb6
Packit 98cdb6
#include "gtkaccelmap.h"
Packit 98cdb6
#include "gtkbox.h"
Packit 98cdb6
#include "gtkclipboard.h"
Packit 98cdb6
#include "gtkdnd.h"
Packit 98cdb6
#include "gtkversion.h"
Packit 98cdb6
#include "gtkmodules.h"
Packit 98cdb6
#include "gtkrc.h"
Packit 98cdb6
#include "gtkrecentmanager.h"
Packit 98cdb6
#include "gtkselection.h"
Packit 98cdb6
#include "gtksettings.h"
Packit 98cdb6
#include "gtkwidget.h"
Packit 98cdb6
#include "gtkwindow.h"
Packit 98cdb6
#include "gtktooltip.h"
Packit 98cdb6
#include "gtkdebug.h"
Packit 98cdb6
#include "gtkalias.h"
Packit 98cdb6
#include "gtkmenu.h"
Packit 98cdb6
#include "gdk/gdkkeysyms.h"
Packit 98cdb6
Packit 98cdb6
#include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
Packit 98cdb6
Packit 98cdb6
#ifdef G_OS_WIN32
Packit 98cdb6
Packit 98cdb6
static HMODULE gtk_dll;
Packit 98cdb6
Packit 98cdb6
BOOL WINAPI
Packit 98cdb6
DllMain (HINSTANCE hinstDLL,
Packit 98cdb6
	 DWORD     fdwReason,
Packit 98cdb6
	 LPVOID    lpvReserved)
Packit 98cdb6
{
Packit 98cdb6
  switch (fdwReason)
Packit 98cdb6
    {
Packit 98cdb6
    case DLL_PROCESS_ATTACH:
Packit 98cdb6
      gtk_dll = (HMODULE) hinstDLL;
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* These here before inclusion of gtkprivate.h so that the original
Packit 98cdb6
 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
Packit 98cdb6
 * bit sucky.
Packit 98cdb6
 */
Packit 98cdb6
const gchar *
Packit 98cdb6
_gtk_get_libdir (void)
Packit 98cdb6
{
Packit 98cdb6
  static char *gtk_libdir = NULL;
Packit 98cdb6
  if (gtk_libdir == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
Packit 98cdb6
      gchar *slash = root ? strrchr (root, '\\') : NULL;
Packit 98cdb6
      if (slash != NULL &&
Packit 98cdb6
          g_ascii_strcasecmp (slash + 1, ".libs") == 0)
Packit 98cdb6
	gtk_libdir = GTK_LIBDIR;
Packit 98cdb6
      else
Packit 98cdb6
	gtk_libdir = g_build_filename (root, "lib", NULL);
Packit 98cdb6
      g_free (root);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return gtk_libdir;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
const gchar *
Packit 98cdb6
_gtk_get_localedir (void)
Packit 98cdb6
{
Packit 98cdb6
  static char *gtk_localedir = NULL;
Packit 98cdb6
  if (gtk_localedir == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      const gchar *p;
Packit 98cdb6
      gchar *root, *temp;
Packit 98cdb6
      
Packit 98cdb6
      /* GTK_LOCALEDIR ends in either /lib/locale or
Packit 98cdb6
       * /share/locale. Scan for that slash.
Packit 98cdb6
       */
Packit 98cdb6
      p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
Packit 98cdb6
      while (*--p != '/')
Packit 98cdb6
	;
Packit 98cdb6
      while (*--p != '/')
Packit 98cdb6
	;
Packit 98cdb6
Packit 98cdb6
      root = g_win32_get_package_installation_directory_of_module (gtk_dll);
Packit 98cdb6
      temp = g_build_filename (root, p, NULL);
Packit 98cdb6
      g_free (root);
Packit 98cdb6
Packit 98cdb6
      /* gtk_localedir is passed to bindtextdomain() which isn't
Packit 98cdb6
       * UTF-8-aware.
Packit 98cdb6
       */
Packit 98cdb6
      gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
Packit 98cdb6
      g_free (temp);
Packit 98cdb6
    }
Packit 98cdb6
  return gtk_localedir;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
#include "gtkprivate.h"
Packit 98cdb6
Packit 98cdb6
/* Private type definitions
Packit 98cdb6
 */
Packit 98cdb6
typedef struct _GtkInitFunction		 GtkInitFunction;
Packit 98cdb6
typedef struct _GtkQuitFunction		 GtkQuitFunction;
Packit 98cdb6
typedef struct _GtkClosure	         GtkClosure;
Packit 98cdb6
typedef struct _GtkKeySnooperData	 GtkKeySnooperData;
Packit 98cdb6
Packit 98cdb6
struct _GtkInitFunction
Packit 98cdb6
{
Packit 98cdb6
  GtkFunction function;
Packit 98cdb6
  gpointer data;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
struct _GtkQuitFunction
Packit 98cdb6
{
Packit 98cdb6
  guint id;
Packit 98cdb6
  guint main_level;
Packit 98cdb6
  GtkCallbackMarshal marshal;
Packit 98cdb6
  GtkFunction function;
Packit 98cdb6
  gpointer data;
Packit 98cdb6
  GDestroyNotify destroy;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
struct _GtkClosure
Packit 98cdb6
{
Packit 98cdb6
  GtkCallbackMarshal marshal;
Packit 98cdb6
  gpointer data;
Packit 98cdb6
  GDestroyNotify destroy;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
struct _GtkKeySnooperData
Packit 98cdb6
{
Packit 98cdb6
  GtkKeySnoopFunc func;
Packit 98cdb6
  gpointer func_data;
Packit 98cdb6
  guint id;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static gint  gtk_quit_invoke_function	 (GtkQuitFunction    *quitf);
Packit 98cdb6
static void  gtk_quit_destroy		 (GtkQuitFunction    *quitf);
Packit 98cdb6
static gint  gtk_invoke_key_snoopers	 (GtkWidget	     *grab_widget,
Packit 98cdb6
					  GdkEvent	     *event);
Packit 98cdb6
Packit 98cdb6
static void     gtk_destroy_closure      (gpointer            data);
Packit 98cdb6
static gboolean gtk_invoke_idle_timeout  (gpointer            data);
Packit 98cdb6
static void     gtk_invoke_input         (gpointer            data,
Packit 98cdb6
					  gint                source,
Packit 98cdb6
					  GdkInputCondition   condition);
Packit 98cdb6
Packit 98cdb6
#if 0
Packit 98cdb6
static void  gtk_error			 (gchar		     *str);
Packit 98cdb6
static void  gtk_warning		 (gchar		     *str);
Packit 98cdb6
static void  gtk_message		 (gchar		     *str);
Packit 98cdb6
static void  gtk_print			 (gchar		     *str);
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
static GtkWindowGroup *gtk_main_get_window_group (GtkWidget   *widget);
Packit 98cdb6
Packit 98cdb6
const guint gtk_major_version = GTK_MAJOR_VERSION;
Packit 98cdb6
const guint gtk_minor_version = GTK_MINOR_VERSION;
Packit 98cdb6
const guint gtk_micro_version = GTK_MICRO_VERSION;
Packit 98cdb6
const guint gtk_binary_age = GTK_BINARY_AGE;
Packit 98cdb6
const guint gtk_interface_age = GTK_INTERFACE_AGE;
Packit 98cdb6
Packit 98cdb6
static guint gtk_main_loop_level = 0;
Packit 98cdb6
static gint pre_initialized = FALSE;
Packit 98cdb6
static gint gtk_initialized = FALSE;
Packit 98cdb6
static GList *current_events = NULL;
Packit 98cdb6
Packit 98cdb6
static GSList *main_loops = NULL;      /* stack of currently executing main loops */
Packit 98cdb6
Packit 98cdb6
static GList *init_functions = NULL;	   /* A list of init functions.
Packit 98cdb6
					    */
Packit 98cdb6
static GList *quit_functions = NULL;	   /* A list of quit functions.
Packit 98cdb6
					    */
Packit 98cdb6
static GSList *key_snoopers = NULL;
Packit 98cdb6
Packit 98cdb6
guint gtk_debug_flags = 0;		   /* Global GTK debug flag */
Packit 98cdb6
Packit 98cdb6
#ifdef G_ENABLE_DEBUG
Packit 98cdb6
static const GDebugKey gtk_debug_keys[] = {
Packit 98cdb6
  {"misc", GTK_DEBUG_MISC},
Packit 98cdb6
  {"plugsocket", GTK_DEBUG_PLUGSOCKET},
Packit 98cdb6
  {"text", GTK_DEBUG_TEXT},
Packit 98cdb6
  {"tree", GTK_DEBUG_TREE},
Packit 98cdb6
  {"updates", GTK_DEBUG_UPDATES},
Packit 98cdb6
  {"keybindings", GTK_DEBUG_KEYBINDINGS},
Packit 98cdb6
  {"multihead", GTK_DEBUG_MULTIHEAD},
Packit 98cdb6
  {"modules", GTK_DEBUG_MODULES},
Packit 98cdb6
  {"geometry", GTK_DEBUG_GEOMETRY},
Packit 98cdb6
  {"icontheme", GTK_DEBUG_ICONTHEME},
Packit 98cdb6
  {"printing", GTK_DEBUG_PRINTING},
Packit 98cdb6
  {"builder", GTK_DEBUG_BUILDER}
Packit 98cdb6
};
Packit 98cdb6
#endif /* G_ENABLE_DEBUG */
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_check_version:
Packit 98cdb6
 * @required_major: the required major version.
Packit 98cdb6
 * @required_minor: the required minor version.
Packit 98cdb6
 * @required_micro: the required micro version.
Packit 98cdb6
 * 
Packit 98cdb6
 * Checks that the GTK+ library in use is compatible with the
Packit 98cdb6
 * given version. Generally you would pass in the constants
Packit 98cdb6
 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
Packit 98cdb6
 * as the three arguments to this function; that produces
Packit 98cdb6
 * a check that the library in use is compatible with
Packit 98cdb6
 * the version of GTK+ the application or module was compiled
Packit 98cdb6
 * against.
Packit 98cdb6
 *
Packit 98cdb6
 * Compatibility is defined by two things: first the version
Packit 98cdb6
 * of the running library is newer than the version
Packit 98cdb6
 * @required_major.required_minor.@required_micro. Second
Packit 98cdb6
 * the running library must be binary compatible with the
Packit 98cdb6
 * version @required_major.required_minor.@required_micro
Packit 98cdb6
 * (same major version.)
Packit 98cdb6
 *
Packit 98cdb6
 * This function is primarily for GTK+ modules; the module
Packit 98cdb6
 * can call this function to check that it wasn't loaded
Packit 98cdb6
 * into an incompatible version of GTK+. However, such a
Packit 98cdb6
 * a check isn't completely reliable, since the module may be
Packit 98cdb6
 * linked against an old version of GTK+ and calling the
Packit 98cdb6
 * old version of gtk_check_version(), but still get loaded
Packit 98cdb6
 * into an application using a newer version of GTK+.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: %NULL if the GTK+ library is compatible with the
Packit 98cdb6
 *   given version, or a string describing the version mismatch.
Packit 98cdb6
 *   The returned string is owned by GTK+ and should not be modified
Packit 98cdb6
 *   or freed.
Packit 98cdb6
 **/
Packit 98cdb6
const gchar*
Packit 98cdb6
gtk_check_version (guint required_major,
Packit 98cdb6
		   guint required_minor,
Packit 98cdb6
		   guint required_micro)
Packit 98cdb6
{
Packit 98cdb6
  gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
Packit 98cdb6
  gint required_effective_micro = 100 * required_minor + required_micro;
Packit 98cdb6
Packit 98cdb6
  if (required_major > GTK_MAJOR_VERSION)
Packit 98cdb6
    return "Gtk+ version too old (major mismatch)";
Packit 98cdb6
  if (required_major < GTK_MAJOR_VERSION)
Packit 98cdb6
    return "Gtk+ version too new (major mismatch)";
Packit 98cdb6
  if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
Packit 98cdb6
    return "Gtk+ version too new (micro mismatch)";
Packit 98cdb6
  if (required_effective_micro > gtk_effective_micro)
Packit 98cdb6
    return "Gtk+ version too old (micro mismatch)";
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* This checks to see if the process is running suid or sgid
Packit 98cdb6
 * at the current time. If so, we don't allow GTK+ to be initialized.
Packit 98cdb6
 * This is meant to be a mild check - we only error out if we
Packit 98cdb6
 * can prove the programmer is doing something wrong, not if
Packit 98cdb6
 * they could be doing something wrong. For this reason, we
Packit 98cdb6
 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
Packit 98cdb6
 */
Packit 98cdb6
static gboolean
Packit 98cdb6
check_setugid (void)
Packit 98cdb6
{
Packit 98cdb6
/* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
Packit 98cdb6
#ifndef G_OS_WIN32
Packit 98cdb6
  uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
Packit 98cdb6
  gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
Packit 98cdb6
  
Packit 98cdb6
#ifdef HAVE_GETRESUID
Packit 98cdb6
  /* These aren't in the header files, so we prototype them here.
Packit 98cdb6
   */
Packit 98cdb6
  int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
Packit 98cdb6
  int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
Packit 98cdb6
Packit 98cdb6
  if (getresuid (&ruid, &euid, &suid) != 0 ||
Packit 98cdb6
      getresgid (&rgid, &egid, &sgid) != 0)
Packit 98cdb6
#endif /* HAVE_GETRESUID */
Packit 98cdb6
    {
Packit 98cdb6
      suid = ruid = getuid ();
Packit 98cdb6
      sgid = rgid = getgid ();
Packit 98cdb6
      euid = geteuid ();
Packit 98cdb6
      egid = getegid ();
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (ruid != euid || ruid != suid ||
Packit 98cdb6
      rgid != egid || rgid != sgid)
Packit 98cdb6
    {
Packit 98cdb6
      g_warning ("This process is currently running setuid or setgid.\n"
Packit 98cdb6
		 "This is not a supported use of GTK+. You must create a helper\n"
Packit 98cdb6
		 "program instead. For further details, see:\n\n"
Packit 98cdb6
		 "    http://www.gtk.org/setuid.html\n\n"
Packit 98cdb6
		 "Refusing to initialize GTK+.");
Packit 98cdb6
      exit (1);
Packit 98cdb6
    }
Packit 98cdb6
#endif
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#ifdef G_OS_WIN32
Packit 98cdb6
Packit 98cdb6
const gchar *
Packit 98cdb6
_gtk_get_datadir (void)
Packit 98cdb6
{
Packit 98cdb6
  static char *gtk_datadir = NULL;
Packit 98cdb6
  if (gtk_datadir == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
Packit 98cdb6
      gtk_datadir = g_build_filename (root, "share", NULL);
Packit 98cdb6
      g_free (root);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return gtk_datadir;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
const gchar *
Packit 98cdb6
_gtk_get_sysconfdir (void)
Packit 98cdb6
{
Packit 98cdb6
  static char *gtk_sysconfdir = NULL;
Packit 98cdb6
  if (gtk_sysconfdir == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
Packit 98cdb6
      gtk_sysconfdir = g_build_filename (root, "etc", NULL);
Packit 98cdb6
      g_free (root);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return gtk_sysconfdir;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
const gchar *
Packit 98cdb6
_gtk_get_data_prefix (void)
Packit 98cdb6
{
Packit 98cdb6
  static char *gtk_data_prefix = NULL;
Packit 98cdb6
  if (gtk_data_prefix == NULL)
Packit 98cdb6
    gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
Packit 98cdb6
Packit 98cdb6
  return gtk_data_prefix;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#endif /* G_OS_WIN32 */
Packit 98cdb6
Packit 98cdb6
static gboolean do_setlocale = TRUE;
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_disable_setlocale:
Packit 98cdb6
 * 
Packit 98cdb6
 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
Packit 98cdb6
 * gtk_parse_args() from automatically
Packit 98cdb6
 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
Packit 98cdb6
 * want to use this function if you wanted to set the locale for
Packit 98cdb6
 * your program to something other than the user's locale, or if
Packit 98cdb6
 * you wanted to set different values for different locale categories.
Packit 98cdb6
 *
Packit 98cdb6
 * Most programs should not need to call this function.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_disable_setlocale (void)
Packit 98cdb6
{
Packit 98cdb6
  if (pre_initialized)
Packit 98cdb6
    g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
Packit 98cdb6
    
Packit 98cdb6
  do_setlocale = FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#ifdef G_PLATFORM_WIN32
Packit 98cdb6
#undef gtk_init_check
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
static GString *gtk_modules_string = NULL;
Packit 98cdb6
static gboolean g_fatal_warnings = FALSE;
Packit 98cdb6
Packit 98cdb6
#ifdef G_ENABLE_DEBUG
Packit 98cdb6
static gboolean
Packit 98cdb6
gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
Packit 98cdb6
{
Packit 98cdb6
  gtk_debug_flags |= g_parse_debug_string (value,
Packit 98cdb6
					   gtk_debug_keys,
Packit 98cdb6
					   G_N_ELEMENTS (gtk_debug_keys));
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
Packit 98cdb6
{
Packit 98cdb6
  gtk_debug_flags &= ~g_parse_debug_string (value,
Packit 98cdb6
					    gtk_debug_keys,
Packit 98cdb6
					    G_N_ELEMENTS (gtk_debug_keys));
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
#endif /* G_ENABLE_DEBUG */
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
Packit 98cdb6
{
Packit 98cdb6
  if (value && *value)
Packit 98cdb6
    {
Packit 98cdb6
      if (gtk_modules_string)
Packit 98cdb6
	g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
Packit 98cdb6
      else
Packit 98cdb6
	gtk_modules_string = g_string_new (NULL);
Packit 98cdb6
      
Packit 98cdb6
      g_string_append (gtk_modules_string, value);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static const GOptionEntry gtk_args[] = {
Packit 98cdb6
  { "gtk-module",       0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,   
Packit 98cdb6
    /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"), 
Packit 98cdb6
    /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
Packit 98cdb6
  { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, 
Packit 98cdb6
    /* Description of --g-fatal-warnings in --help output */   N_("Make all warnings fatal"), NULL },
Packit 98cdb6
#ifdef G_ENABLE_DEBUG
Packit 98cdb6
  { "gtk-debug",        0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,    
Packit 98cdb6
    /* Description of --gtk-debug=FLAGS in --help output */    N_("GTK+ debugging flags to set"), 
Packit 98cdb6
    /* Placeholder in --gtk-debug=FLAGS in --help output */    N_("FLAGS") },
Packit 98cdb6
  { "gtk-no-debug",     0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb, 
Packit 98cdb6
    /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"), 
Packit 98cdb6
    /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
Packit 98cdb6
#endif 
Packit 98cdb6
  { NULL }
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
#ifdef G_OS_WIN32
Packit 98cdb6
Packit 98cdb6
static char *iso639_to_check = NULL;
Packit 98cdb6
static char *iso3166_to_check = NULL;
Packit 98cdb6
static char *script_to_check = NULL;
Packit 98cdb6
static gboolean setlocale_called = FALSE;
Packit 98cdb6
Packit 98cdb6
static BOOL CALLBACK
Packit 98cdb6
enum_locale_proc (LPTSTR locale)
Packit 98cdb6
{
Packit 98cdb6
  LCID lcid;
Packit 98cdb6
  char iso639[10];
Packit 98cdb6
  char iso3166[10];
Packit 98cdb6
  char *endptr;
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  lcid = strtoul (locale, &endptr, 16);
Packit 98cdb6
  if (*endptr == '\0' &&
Packit 98cdb6
      GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
Packit 98cdb6
      GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
Packit 98cdb6
    {
Packit 98cdb6
      if (strcmp (iso639, iso639_to_check) == 0 &&
Packit 98cdb6
	  ((iso3166_to_check != NULL &&
Packit 98cdb6
	    strcmp (iso3166, iso3166_to_check) == 0) ||
Packit 98cdb6
	   (iso3166_to_check == NULL &&
Packit 98cdb6
	    SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
Packit 98cdb6
	{
Packit 98cdb6
	  char language[100], country[100];
Packit 98cdb6
	  char locale[300];
Packit 98cdb6
Packit 98cdb6
	  if (script_to_check != NULL)
Packit 98cdb6
	    {
Packit 98cdb6
	      /* If lcid is the "other" script for this language,
Packit 98cdb6
	       * return TRUE, i.e. continue looking.
Packit 98cdb6
	       */
Packit 98cdb6
	      if (strcmp (script_to_check, "Latn") == 0)
Packit 98cdb6
		{
Packit 98cdb6
		  switch (LANGIDFROMLCID (lcid))
Packit 98cdb6
		    {
Packit 98cdb6
		    case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    case MAKELANGID (LANG_SERBIAN, 0x07):
Packit 98cdb6
		      /* Serbian in Bosnia and Herzegovina, Cyrillic */
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    }
Packit 98cdb6
		}
Packit 98cdb6
	      else if (strcmp (script_to_check, "Cyrl") == 0)
Packit 98cdb6
		{
Packit 98cdb6
		  switch (LANGIDFROMLCID (lcid))
Packit 98cdb6
		    {
Packit 98cdb6
		    case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    case MAKELANGID (LANG_SERBIAN, 0x06):
Packit 98cdb6
		      /* Serbian in Bosnia and Herzegovina, Latin */
Packit 98cdb6
		      return TRUE;
Packit 98cdb6
		    }
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
Packit 98cdb6
	  SetThreadLocale (lcid);
Packit 98cdb6
Packit 98cdb6
	  if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
Packit 98cdb6
	      GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
Packit 98cdb6
	    {
Packit 98cdb6
	      strcpy (locale, language);
Packit 98cdb6
	      strcat (locale, "_");
Packit 98cdb6
	      strcat (locale, country);
Packit 98cdb6
Packit 98cdb6
	      if (setlocale (LC_ALL, locale) != NULL)
Packit 98cdb6
		setlocale_called = TRUE;
Packit 98cdb6
	    }
Packit 98cdb6
Packit 98cdb6
	  return FALSE;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
  
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
setlocale_initialization (void)
Packit 98cdb6
{
Packit 98cdb6
  static gboolean initialized = FALSE;
Packit 98cdb6
Packit 98cdb6
  if (initialized)
Packit 98cdb6
    return;
Packit 98cdb6
  initialized = TRUE;
Packit 98cdb6
Packit 98cdb6
  if (do_setlocale)
Packit 98cdb6
    {
Packit 98cdb6
#ifdef G_OS_WIN32
Packit 98cdb6
      /* If some of the POSIXish environment variables are set, set
Packit 98cdb6
       * the Win32 thread locale correspondingly.
Packit 98cdb6
       */ 
Packit 98cdb6
      char *p = getenv ("LC_ALL");
Packit 98cdb6
      if (p == NULL)
Packit 98cdb6
	p = getenv ("LANG");
Packit 98cdb6
Packit 98cdb6
      if (p != NULL)
Packit 98cdb6
	{
Packit 98cdb6
	  p = g_strdup (p);
Packit 98cdb6
	  if (strcmp (p, "C") == 0)
Packit 98cdb6
	    SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
Packit 98cdb6
	  else
Packit 98cdb6
	    {
Packit 98cdb6
	      /* Check if one of the supported locales match the
Packit 98cdb6
	       * environment variable. If so, use that locale.
Packit 98cdb6
	       */
Packit 98cdb6
	      iso639_to_check = p;
Packit 98cdb6
	      iso3166_to_check = strchr (iso639_to_check, '_');
Packit 98cdb6
	      if (iso3166_to_check != NULL)
Packit 98cdb6
		{
Packit 98cdb6
		  *iso3166_to_check++ = '\0';
Packit 98cdb6
Packit 98cdb6
		  script_to_check = strchr (iso3166_to_check, '@');
Packit 98cdb6
		  if (script_to_check != NULL)
Packit 98cdb6
		    *script_to_check++ = '\0';
Packit 98cdb6
Packit 98cdb6
		  /* Handle special cases. */
Packit 98cdb6
		  
Packit 98cdb6
		  /* The standard code for Serbia and Montenegro was
Packit 98cdb6
		   * "CS", but MSFT uses for some reason "SP". By now
Packit 98cdb6
		   * (October 2006), SP has split into two, "RS" and
Packit 98cdb6
		   * "ME", but don't bother trying to handle those
Packit 98cdb6
		   * yet. Do handle the even older "YU", though.
Packit 98cdb6
		   */
Packit 98cdb6
		  if (strcmp (iso3166_to_check, "CS") == 0 ||
Packit 98cdb6
		      strcmp (iso3166_to_check, "YU") == 0)
Packit 98cdb6
		    iso3166_to_check = "SP";
Packit 98cdb6
		}
Packit 98cdb6
	      else
Packit 98cdb6
		{
Packit 98cdb6
		  script_to_check = strchr (iso639_to_check, '@');
Packit 98cdb6
		  if (script_to_check != NULL)
Packit 98cdb6
		    *script_to_check++ = '\0';
Packit 98cdb6
		  /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
Packit 98cdb6
		  if (strcmp (iso639_to_check, "sr") == 0)
Packit 98cdb6
		    iso3166_to_check = "SP";
Packit 98cdb6
		}
Packit 98cdb6
Packit 98cdb6
	      EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
Packit 98cdb6
	    }
Packit 98cdb6
	  g_free (p);
Packit 98cdb6
	}
Packit 98cdb6
      if (!setlocale_called)
Packit 98cdb6
	setlocale (LC_ALL, "");
Packit 98cdb6
#else
Packit 98cdb6
      if (!setlocale (LC_ALL, ""))
Packit 98cdb6
	g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
Packit 98cdb6
#endif
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* Return TRUE if module_to_check causes version conflicts.
Packit 98cdb6
 * If module_to_check is NULL, check the main module.
Packit 98cdb6
 */
Packit 98cdb6
gboolean
Packit 98cdb6
_gtk_module_has_mixed_deps (GModule *module_to_check)
Packit 98cdb6
{
Packit 98cdb6
  GModule *module;
Packit 98cdb6
  gpointer func;
Packit 98cdb6
  gboolean result;
Packit 98cdb6
Packit 98cdb6
  if (!module_to_check)
Packit 98cdb6
    module = g_module_open (NULL, 0);
Packit 98cdb6
  else
Packit 98cdb6
    module = module_to_check;
Packit 98cdb6
Packit 98cdb6
  if (g_module_symbol (module, "gtk_widget_device_is_shadowed", &func))
Packit 98cdb6
    result = TRUE;
Packit 98cdb6
  else
Packit 98cdb6
    result = FALSE;
Packit 98cdb6
Packit 98cdb6
  if (!module_to_check)
Packit 98cdb6
    g_module_close (module);
Packit 98cdb6
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_pre_parse_initialization (int    *argc,
Packit 98cdb6
			     char ***argv)
Packit 98cdb6
{
Packit 98cdb6
  const gchar *env_string;
Packit 98cdb6
  
Packit 98cdb6
#if	0
Packit 98cdb6
  g_set_error_handler (gtk_error);
Packit 98cdb6
  g_set_warning_handler (gtk_warning);
Packit 98cdb6
  g_set_message_handler (gtk_message);
Packit 98cdb6
  g_set_print_handler (gtk_print);
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
  if (pre_initialized)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  pre_initialized = TRUE;
Packit 98cdb6
Packit 98cdb6
  if (_gtk_module_has_mixed_deps (NULL))
Packit 98cdb6
    g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
Packit 98cdb6
Packit 98cdb6
  gdk_pre_parse_libgtk_only ();
Packit 98cdb6
  gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
Packit 98cdb6
  
Packit 98cdb6
#ifdef G_ENABLE_DEBUG
Packit 98cdb6
  env_string = g_getenv ("GTK_DEBUG");
Packit 98cdb6
  if (env_string != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gtk_debug_flags = g_parse_debug_string (env_string,
Packit 98cdb6
					      gtk_debug_keys,
Packit 98cdb6
					      G_N_ELEMENTS (gtk_debug_keys));
Packit 98cdb6
      env_string = NULL;
Packit 98cdb6
    }
Packit 98cdb6
#endif	/* G_ENABLE_DEBUG */
Packit 98cdb6
Packit 98cdb6
  env_string = g_getenv ("GTK2_MODULES");
Packit 98cdb6
  if (env_string)
Packit 98cdb6
    gtk_modules_string = g_string_new (env_string);
Packit 98cdb6
Packit 98cdb6
  env_string = g_getenv ("GTK_MODULES");
Packit 98cdb6
  if (env_string)
Packit 98cdb6
    {
Packit 98cdb6
      if (gtk_modules_string)
Packit 98cdb6
        g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
Packit 98cdb6
      else
Packit 98cdb6
        gtk_modules_string = g_string_new (NULL);
Packit 98cdb6
Packit 98cdb6
      g_string_append (gtk_modules_string, env_string);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gettext_initialization (void)
Packit 98cdb6
{
Packit 98cdb6
  setlocale_initialization ();
Packit 98cdb6
Packit 98cdb6
#ifdef ENABLE_NLS
Packit 98cdb6
  bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
Packit 98cdb6
  bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
Packit 98cdb6
#    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
Packit 98cdb6
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
Packit 98cdb6
  bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
Packit 98cdb6
#    endif
Packit 98cdb6
#endif  
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_post_parse_initialization (int    *argc,
Packit 98cdb6
			      char ***argv)
Packit 98cdb6
{
Packit 98cdb6
  if (gtk_initialized)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  gettext_initialization ();
Packit 98cdb6
Packit 98cdb6
#ifdef SIGPIPE
Packit 98cdb6
  signal (SIGPIPE, SIG_IGN);
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
  if (g_fatal_warnings)
Packit 98cdb6
    {
Packit 98cdb6
      GLogLevelFlags fatal_mask;
Packit 98cdb6
Packit 98cdb6
      fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
Packit 98cdb6
      fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
Packit 98cdb6
      g_log_set_always_fatal (fatal_mask);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (gtk_debug_flags & GTK_DEBUG_UPDATES)
Packit 98cdb6
    gdk_window_set_debug_updates (TRUE);
Packit 98cdb6
Packit 98cdb6
  {
Packit 98cdb6
  /* Translate to default:RTL if you want your widgets
Packit 98cdb6
   * to be RTL, otherwise translate to default:LTR.
Packit 98cdb6
   * Do *not* translate it to "predefinito:LTR", if it
Packit 98cdb6
   * it isn't default:LTR or default:RTL it will not work 
Packit 98cdb6
   */
Packit 98cdb6
    char *e = _("default:LTR");
Packit 98cdb6
    if (strcmp (e, "default:RTL")==0) 
Packit 98cdb6
      gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
Packit 98cdb6
    else if (strcmp (e, "default:LTR"))
Packit 98cdb6
      g_warning ("Whoever translated default:LTR did so wrongly.\n");
Packit 98cdb6
  }
Packit 98cdb6
Packit 98cdb6
  /* do what the call to gtk_type_init() used to do */
Packit 98cdb6
  g_type_init ();
Packit 98cdb6
Packit 98cdb6
  _gtk_accel_map_init ();
Packit 98cdb6
  _gtk_rc_init ();
Packit 98cdb6
Packit 98cdb6
  /* Set the 'initialized' flag.
Packit 98cdb6
   */
Packit 98cdb6
  gtk_initialized = TRUE;
Packit 98cdb6
Packit 98cdb6
  /* load gtk modules */
Packit 98cdb6
  if (gtk_modules_string)
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_modules_init (argc, argv, gtk_modules_string->str);
Packit 98cdb6
      g_string_free (gtk_modules_string, TRUE);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_modules_init (argc, argv, NULL);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
typedef struct
Packit 98cdb6
{
Packit 98cdb6
  gboolean open_default_display;
Packit 98cdb6
} OptionGroupInfo;
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
pre_parse_hook (GOptionContext *context,
Packit 98cdb6
		GOptionGroup   *group,
Packit 98cdb6
		gpointer	data,
Packit 98cdb6
		GError        **error)
Packit 98cdb6
{
Packit 98cdb6
  do_pre_parse_initialization (NULL, NULL);
Packit 98cdb6
  
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
post_parse_hook (GOptionContext *context,
Packit 98cdb6
		 GOptionGroup   *group,
Packit 98cdb6
		 gpointer	data,
Packit 98cdb6
		 GError        **error)
Packit 98cdb6
{
Packit 98cdb6
  OptionGroupInfo *info = data;
Packit 98cdb6
Packit 98cdb6
  
Packit 98cdb6
  do_post_parse_initialization (NULL, NULL);
Packit 98cdb6
  
Packit 98cdb6
  if (info->open_default_display)
Packit 98cdb6
    {
Packit 98cdb6
      if (gdk_display_open_default_libgtk_only () == NULL)
Packit 98cdb6
	{
Packit 98cdb6
	  const char *display_name = gdk_get_display_arg_name ();
Packit 98cdb6
	  g_set_error (error, 
Packit 98cdb6
		       G_OPTION_ERROR, 
Packit 98cdb6
		       G_OPTION_ERROR_FAILED,
Packit 98cdb6
		       _("Cannot open display: %s"),
Packit 98cdb6
		       display_name ? display_name : "" );
Packit 98cdb6
	  
Packit 98cdb6
	  return FALSE;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_get_option_group:
Packit 98cdb6
 * @open_default_display: whether to open the default display 
Packit 98cdb6
 *    when parsing the commandline arguments
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns a #GOptionGroup for the commandline arguments recognized
Packit 98cdb6
 * by GTK+ and GDK. You should add this group to your #GOptionContext 
Packit 98cdb6
 * with g_option_context_add_group(), if you are using 
Packit 98cdb6
 * g_option_context_parse() to parse your commandline arguments.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns: a #GOptionGroup for the commandline arguments recognized
Packit 98cdb6
 *   by GTK+
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.6
Packit 98cdb6
 */
Packit 98cdb6
GOptionGroup *
Packit 98cdb6
gtk_get_option_group (gboolean open_default_display)
Packit 98cdb6
{
Packit 98cdb6
  GOptionGroup *group;
Packit 98cdb6
  OptionGroupInfo *info;
Packit 98cdb6
Packit 98cdb6
  gettext_initialization ();
Packit 98cdb6
Packit 98cdb6
  info = g_new0 (OptionGroupInfo, 1);
Packit 98cdb6
  info->open_default_display = open_default_display;
Packit 98cdb6
  
Packit 98cdb6
  group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
Packit 98cdb6
  g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
Packit 98cdb6
Packit 98cdb6
  gdk_add_option_entries_libgtk_only (group);
Packit 98cdb6
  g_option_group_add_entries (group, gtk_args);
Packit 98cdb6
  g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
Packit 98cdb6
  
Packit 98cdb6
  return group;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_init_with_args:
Packit 98cdb6
 * @argc: a pointer to the number of command line arguments.
Packit 98cdb6
 * @argv: (inout) (array length=argc): a pointer to the array of
Packit 98cdb6
 *    command line arguments.
Packit 98cdb6
 * @parameter_string: a string which is displayed in
Packit 98cdb6
 *    the first line of <option>--help</option> output, after 
Packit 98cdb6
 *    <literal><replaceable>programname</replaceable> [OPTION...]</literal>
Packit 98cdb6
 * @entries: (array zero-terminated=1):  a %NULL-terminated array
Packit 98cdb6
 *    of #GOptionEntrys describing the options of your program
Packit 98cdb6
 * @translation_domain: a translation domain to use for translating
Packit 98cdb6
 *    the <option>--help</option> output for the options in @entries
Packit 98cdb6
 *    and the @parameter_string with gettext(), or %NULL
Packit 98cdb6
 * @error: a return location for errors 
Packit 98cdb6
 *
Packit 98cdb6
 * This function does the same work as gtk_init_check(). 
Packit 98cdb6
 * Additionally, it allows you to add your own commandline options, 
Packit 98cdb6
 * and it automatically generates nicely formatted 
Packit 98cdb6
 * <option>--help</option> output. Note that your program will
Packit 98cdb6
 * be terminated after writing out the help output.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns: %TRUE if the GUI has been successfully initialized, 
Packit 98cdb6
 *               %FALSE otherwise.
Packit 98cdb6
 * 
Packit 98cdb6
 * Since: 2.6
Packit 98cdb6
 */
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_init_with_args (int            *argc,
Packit 98cdb6
		    char         ***argv,
Packit 98cdb6
		    const char     *parameter_string,
Packit 98cdb6
		    GOptionEntry   *entries,
Packit 98cdb6
		    const char     *translation_domain,
Packit 98cdb6
		    GError        **error)
Packit 98cdb6
{
Packit 98cdb6
  GOptionContext *context;
Packit 98cdb6
  GOptionGroup *gtk_group;
Packit 98cdb6
  gboolean retval;
Packit 98cdb6
Packit 98cdb6
  if (gtk_initialized)
Packit 98cdb6
    return gdk_display_open_default_libgtk_only () != NULL;
Packit 98cdb6
Packit 98cdb6
  gettext_initialization ();
Packit 98cdb6
Packit 98cdb6
  if (!check_setugid ())
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  gtk_group = gtk_get_option_group (TRUE);
Packit 98cdb6
  
Packit 98cdb6
  context = g_option_context_new (parameter_string);
Packit 98cdb6
  g_option_context_add_group (context, gtk_group);
Packit 98cdb6
  
Packit 98cdb6
  g_option_context_set_translation_domain (context, translation_domain);
Packit 98cdb6
Packit 98cdb6
  if (entries)
Packit 98cdb6
    g_option_context_add_main_entries (context, entries, translation_domain);
Packit 98cdb6
  retval = g_option_context_parse (context, argc, argv, error);
Packit 98cdb6
  
Packit 98cdb6
  g_option_context_free (context);
Packit 98cdb6
Packit 98cdb6
  return retval;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_parse_args:
Packit 98cdb6
 * @argc: (inout): a pointer to the number of command line arguments
Packit 98cdb6
 * @argv: (array length=argc) (inout): a pointer to the array of
Packit 98cdb6
 *     command line arguments
Packit 98cdb6
 *
Packit 98cdb6
 * Parses command line arguments, and initializes global
Packit 98cdb6
 * attributes of GTK+, but does not actually open a connection
Packit 98cdb6
 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
Packit 98cdb6
 *
Packit 98cdb6
 * Any arguments used by GTK+ or GDK are removed from the array and
Packit 98cdb6
 * @argc and @argv are updated accordingly.
Packit 98cdb6
 *
Packit 98cdb6
 * There is no need to call this function explicitely if you are using
Packit 98cdb6
 * gtk_init(), or gtk_init_check().
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_parse_args (int    *argc,
Packit 98cdb6
		char ***argv)
Packit 98cdb6
{
Packit 98cdb6
  GOptionContext *option_context;
Packit 98cdb6
  GOptionGroup *gtk_group;
Packit 98cdb6
  GError *error = NULL;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_initialized)
Packit 98cdb6
    return TRUE;
Packit 98cdb6
Packit 98cdb6
  gettext_initialization ();
Packit 98cdb6
Packit 98cdb6
  if (!check_setugid ())
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  option_context = g_option_context_new (NULL);
Packit 98cdb6
  g_option_context_set_ignore_unknown_options (option_context, TRUE);
Packit 98cdb6
  g_option_context_set_help_enabled (option_context, FALSE);
Packit 98cdb6
  gtk_group = gtk_get_option_group (FALSE);
Packit 98cdb6
  g_option_context_set_main_group (option_context, gtk_group);
Packit 98cdb6
  if (!g_option_context_parse (option_context, argc, argv, &error))
Packit 98cdb6
    {
Packit 98cdb6
      g_warning ("%s", error->message);
Packit 98cdb6
      g_error_free (error);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_option_context_free (option_context);
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#ifdef G_PLATFORM_WIN32
Packit 98cdb6
#undef gtk_init_check
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_init_check:
Packit 98cdb6
 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
Packit 98cdb6
 *   main() function. Changed if any arguments were handled.
Packit 98cdb6
 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
Packit 98cdb6
 *   Any parameters understood by gtk_init() are stripped before return.
Packit 98cdb6
 *
Packit 98cdb6
 * This function does the same work as gtk_init() with only
Packit 98cdb6
 * a single change: It does not terminate the program if the GUI can't be
Packit 98cdb6
 * initialized. Instead it returns %FALSE on failure.
Packit 98cdb6
 *
Packit 98cdb6
 * This way the application can fall back to some other means of communication 
Packit 98cdb6
 * with the user - for example a curses or command line interface.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE if the GUI has been successfully initialized, 
Packit 98cdb6
 *               %FALSE otherwise.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_init_check (int	 *argc,
Packit 98cdb6
		char   ***argv)
Packit 98cdb6
{
Packit 98cdb6
  if (!gtk_parse_args (argc, argv))
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  return gdk_display_open_default_libgtk_only () != NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#ifdef G_PLATFORM_WIN32
Packit 98cdb6
#undef gtk_init
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_init:
Packit 98cdb6
 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of
Packit 98cdb6
 *     your main() function. Changed if any arguments were handled
Packit 98cdb6
 * @argv: (array length=argc) (inout) (allow-none): Address of the
Packit 98cdb6
 *     <parameter>argv</parameter> parameter of main(). Any options
Packit 98cdb6
 *     understood by GTK+ are stripped before return.
Packit 98cdb6
 *
Packit 98cdb6
 * Call this function before using any other GTK+ functions in your GUI
Packit 98cdb6
 * applications.  It will initialize everything needed to operate the
Packit 98cdb6
 * toolkit and parses some standard command line options.
Packit 98cdb6
 *
Packit 98cdb6
 * @argc and @argv are adjusted accordingly so your own code will
Packit 98cdb6
 * never see those standard arguments.
Packit 98cdb6
 *
Packit 98cdb6
 * Note that there are some alternative ways to initialize GTK+:
Packit 98cdb6
 * if you are calling gtk_parse_args(), gtk_init_check(),
Packit 98cdb6
 * gtk_init_with_args() or g_option_context_parse() with
Packit 98cdb6
 * the option group returned by gtk_get_option_group(),
Packit 98cdb6
 * you <emphasis>don't</emphasis> have to call gtk_init().
Packit 98cdb6
 *
Packit 98cdb6
 * <note><para>
Packit 98cdb6
 * This function will terminate your program if it was unable to
Packit 98cdb6
 * initialize the windowing system for some reason. If you want
Packit 98cdb6
 * your program to fall back to a textual interface you want to
Packit 98cdb6
 * call gtk_init_check() instead.
Packit 98cdb6
 * </para></note>
Packit 98cdb6
 *
Packit 98cdb6
 * <note><para>
Packit 98cdb6
 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
Packit 98cdb6
 * during initialization, to ignore SIGPIPE signals, since these are
Packit 98cdb6
 * almost never wanted in graphical applications. If you do need to
Packit 98cdb6
 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
Packit 98cdb6
 * but notice that other libraries (e.g. libdbus or gvfs) might do
Packit 98cdb6
 * similar things.
Packit 98cdb6
 * </para></note>
Packit 98cdb6
 */
Packit 98cdb6
void
Packit 98cdb6
gtk_init (int *argc, char ***argv)
Packit 98cdb6
{
Packit 98cdb6
  if (!gtk_init_check (argc, argv))
Packit 98cdb6
    {
Packit 98cdb6
      const char *display_name_arg = gdk_get_display_arg_name ();
Packit 98cdb6
      if (display_name_arg == NULL)
Packit 98cdb6
        display_name_arg = getenv("DISPLAY");
Packit 98cdb6
      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
Packit 98cdb6
      exit (1);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#ifdef G_PLATFORM_WIN32
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
Packit 98cdb6
{
Packit 98cdb6
  if (sizeof_GtkWindow != sizeof (GtkWindow))
Packit 98cdb6
    g_error ("Incompatible build!\n"
Packit 98cdb6
	     "The code using GTK+ thinks GtkWindow is of different\n"
Packit 98cdb6
             "size than it actually is in this build of GTK+.\n"
Packit 98cdb6
	     "On Windows, this probably means that you have compiled\n"
Packit 98cdb6
	     "your code with gcc without the -mms-bitfields switch,\n"
Packit 98cdb6
	     "or that you are using an unsupported compiler.");
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* In GTK+ 2.0 the GtkWindow struct actually is the same size in
Packit 98cdb6
 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
Packit 98cdb6
 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
Packit 98cdb6
 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
Packit 98cdb6
 * -fnative-struct still matters. GtkBox is one such.
Packit 98cdb6
 */
Packit 98cdb6
static void
Packit 98cdb6
check_sizeof_GtkBox (size_t sizeof_GtkBox)
Packit 98cdb6
{
Packit 98cdb6
  if (sizeof_GtkBox != sizeof (GtkBox))
Packit 98cdb6
    g_error ("Incompatible build!\n"
Packit 98cdb6
	     "The code using GTK+ thinks GtkBox is of different\n"
Packit 98cdb6
             "size than it actually is in this build of GTK+.\n"
Packit 98cdb6
	     "On Windows, this probably means that you have compiled\n"
Packit 98cdb6
	     "your code with gcc without the -mms-bitfields switch,\n"
Packit 98cdb6
	     "or that you are using an unsupported compiler.");
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* These two functions might get more checks added later, thus pass
Packit 98cdb6
 * in the number of extra args.
Packit 98cdb6
 */
Packit 98cdb6
void
Packit 98cdb6
gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
Packit 98cdb6
{
Packit 98cdb6
  check_sizeof_GtkWindow (sizeof_GtkWindow);
Packit 98cdb6
  if (num_checks >= 2)
Packit 98cdb6
    check_sizeof_GtkBox (sizeof_GtkBox);
Packit 98cdb6
  gtk_init (argc, argv);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
Packit 98cdb6
{
Packit 98cdb6
  check_sizeof_GtkWindow (sizeof_GtkWindow);
Packit 98cdb6
  if (num_checks >= 2)
Packit 98cdb6
    check_sizeof_GtkBox (sizeof_GtkBox);
Packit 98cdb6
  return gtk_init_check (argc, argv);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_exit (gint errorcode)
Packit 98cdb6
{
Packit 98cdb6
  exit (errorcode);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_set_locale:
Packit 98cdb6
 *
Packit 98cdb6
 * Initializes internationalization support for GTK+. gtk_init()
Packit 98cdb6
 * automatically does this, so there is typically no point
Packit 98cdb6
 * in calling this function.
Packit 98cdb6
 *
Packit 98cdb6
 * If you are calling this function because you changed the locale
Packit 98cdb6
 * after GTK+ is was initialized, then calling this function
Packit 98cdb6
 * may help a bit. (Note, however, that changing the locale
Packit 98cdb6
 * after GTK+ is initialized may produce inconsistent results and
Packit 98cdb6
 * is not really supported.)
Packit 98cdb6
 * 
Packit 98cdb6
 * In detail - sets the current locale according to the
Packit 98cdb6
 * program environment. This is the same as calling the C library function
Packit 98cdb6
 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the 
Packit 98cdb6
 * locale specific setup of the windowing system used by GDK.
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns: a string corresponding to the locale set, typically in the
Packit 98cdb6
 * form lang_COUNTRY, where lang is an ISO-639 language code, and
Packit 98cdb6
 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
Packit 98cdb6
 * result of the setlocale(); it is also used on other machines, such as 
Packit 98cdb6
 * Windows, where the C library returns a different result. The string is 
Packit 98cdb6
 * owned by GTK+ and should not be modified or freed.
Packit 98cdb6
 *
Packit 98cdb6
 * Deprecated: 2.24: Use setlocale() directly
Packit 98cdb6
 **/
Packit 98cdb6
gchar *
Packit 98cdb6
gtk_set_locale (void)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_set_locale ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_get_lc_ctype:
Packit 98cdb6
 *
Packit 98cdb6
 * Return the Unix-style locale string for the language currently in
Packit 98cdb6
 * effect. On Unix systems, this is the return value from
Packit 98cdb6
 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
Packit 98cdb6
 * affect this through the environment variables LC_ALL, LC_CTYPE or
Packit 98cdb6
 * LANG (checked in that order). The locale strings typically is in
Packit 98cdb6
 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
Packit 98cdb6
 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
Packit 98cdb6
 * Swedish as written in Finland or pt_BR for Portuguese as written in
Packit 98cdb6
 * Brazil.
Packit 98cdb6
 * 
Packit 98cdb6
 * On Windows, the C library doesn't use any such environment
Packit 98cdb6
 * variables, and setting them won't affect the behaviour of functions
Packit 98cdb6
 * like ctime(). The user sets the locale through the Regional Options 
Packit 98cdb6
 * in the Control Panel. The C library (in the setlocale() function) 
Packit 98cdb6
 * does not use country and language codes, but country and language 
Packit 98cdb6
 * names spelled out in English. 
Packit 98cdb6
 * However, this function does check the above environment
Packit 98cdb6
 * variables, and does return a Unix-style locale string based on
Packit 98cdb6
 * either said environment variables or the thread's current locale.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: a dynamically allocated string, free with g_free().
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
gchar *
Packit 98cdb6
_gtk_get_lc_ctype (void)
Packit 98cdb6
{
Packit 98cdb6
#ifdef G_OS_WIN32
Packit 98cdb6
  /* Somebody might try to set the locale for this process using the
Packit 98cdb6
   * LANG or LC_ environment variables. The Microsoft C library
Packit 98cdb6
   * doesn't know anything about them. You set the locale in the
Packit 98cdb6
   * Control Panel. Setting these env vars won't have any affect on
Packit 98cdb6
   * locale-dependent C library functions like ctime(). But just for
Packit 98cdb6
   * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
Packit 98cdb6
   * it easier to test GTK and Pango in various default languages, you
Packit 98cdb6
   * don't have to clickety-click in the Control Panel, you can simply
Packit 98cdb6
   * start the program with LC_ALL=something on the command line.)
Packit 98cdb6
   */
Packit 98cdb6
  gchar *p;
Packit 98cdb6
Packit 98cdb6
  p = getenv ("LC_ALL");
Packit 98cdb6
  if (p != NULL)
Packit 98cdb6
    return g_strdup (p);
Packit 98cdb6
Packit 98cdb6
  p = getenv ("LC_CTYPE");
Packit 98cdb6
  if (p != NULL)
Packit 98cdb6
    return g_strdup (p);
Packit 98cdb6
Packit 98cdb6
  p = getenv ("LANG");
Packit 98cdb6
  if (p != NULL)
Packit 98cdb6
    return g_strdup (p);
Packit 98cdb6
Packit 98cdb6
  return g_win32_getlocale ();
Packit 98cdb6
#else
Packit 98cdb6
  return g_strdup (setlocale (LC_CTYPE, NULL));
Packit 98cdb6
#endif
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_get_default_language:
Packit 98cdb6
 *
Packit 98cdb6
 * Returns the #PangoLanguage for the default language currently in
Packit 98cdb6
 * effect. (Note that this can change over the life of an
Packit 98cdb6
 * application.)  The default language is derived from the current
Packit 98cdb6
 * locale. It determines, for example, whether GTK+ uses the
Packit 98cdb6
 * right-to-left or left-to-right text direction.
Packit 98cdb6
 *
Packit 98cdb6
 * This function is equivalent to pango_language_get_default().  See
Packit 98cdb6
 * that function for details.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: the default language as a #PangoLanguage, must not be
Packit 98cdb6
 * freed
Packit 98cdb6
 **/
Packit 98cdb6
PangoLanguage *
Packit 98cdb6
gtk_get_default_language (void)
Packit 98cdb6
{
Packit 98cdb6
  return pango_language_get_default ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_main (void)
Packit 98cdb6
{
Packit 98cdb6
  GList *tmp_list;
Packit 98cdb6
  GList *functions;
Packit 98cdb6
  GtkInitFunction *init;
Packit 98cdb6
  GMainLoop *loop;
Packit 98cdb6
Packit 98cdb6
  gtk_main_loop_level++;
Packit 98cdb6
  
Packit 98cdb6
  loop = g_main_loop_new (NULL, TRUE);
Packit 98cdb6
  main_loops = g_slist_prepend (main_loops, loop);
Packit 98cdb6
Packit 98cdb6
  tmp_list = functions = init_functions;
Packit 98cdb6
  init_functions = NULL;
Packit 98cdb6
  
Packit 98cdb6
  while (tmp_list)
Packit 98cdb6
    {
Packit 98cdb6
      init = tmp_list->data;
Packit 98cdb6
      tmp_list = tmp_list->next;
Packit 98cdb6
      
Packit 98cdb6
      (* init->function) (init->data);
Packit 98cdb6
      g_free (init);
Packit 98cdb6
    }
Packit 98cdb6
  g_list_free (functions);
Packit 98cdb6
Packit 98cdb6
  if (g_main_loop_is_running (main_loops->data))
Packit 98cdb6
    {
Packit 98cdb6
      GDK_THREADS_LEAVE ();
Packit 98cdb6
      g_main_loop_run (loop);
Packit 98cdb6
      GDK_THREADS_ENTER ();
Packit 98cdb6
      gdk_flush ();
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (quit_functions)
Packit 98cdb6
    {
Packit 98cdb6
      GList *reinvoke_list = NULL;
Packit 98cdb6
      GtkQuitFunction *quitf;
Packit 98cdb6
Packit 98cdb6
      while (quit_functions)
Packit 98cdb6
	{
Packit 98cdb6
	  quitf = quit_functions->data;
Packit 98cdb6
Packit 98cdb6
	  tmp_list = quit_functions;
Packit 98cdb6
	  quit_functions = g_list_remove_link (quit_functions, quit_functions);
Packit 98cdb6
	  g_list_free_1 (tmp_list);
Packit 98cdb6
Packit 98cdb6
	  if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
Packit 98cdb6
	      gtk_quit_invoke_function (quitf))
Packit 98cdb6
	    {
Packit 98cdb6
	      reinvoke_list = g_list_prepend (reinvoke_list, quitf);
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    {
Packit 98cdb6
	      gtk_quit_destroy (quitf);
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      if (reinvoke_list)
Packit 98cdb6
	{
Packit 98cdb6
	  GList *work;
Packit 98cdb6
	  
Packit 98cdb6
	  work = g_list_last (reinvoke_list);
Packit 98cdb6
	  if (quit_functions)
Packit 98cdb6
	    quit_functions->prev = work;
Packit 98cdb6
	  work->next = quit_functions;
Packit 98cdb6
	  quit_functions = work;
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      gdk_flush ();
Packit 98cdb6
    }
Packit 98cdb6
    
Packit 98cdb6
  main_loops = g_slist_remove (main_loops, loop);
Packit 98cdb6
Packit 98cdb6
  g_main_loop_unref (loop);
Packit 98cdb6
Packit 98cdb6
  gtk_main_loop_level--;
Packit 98cdb6
Packit 98cdb6
  if (gtk_main_loop_level == 0)
Packit 98cdb6
    {
Packit 98cdb6
      /* Try storing all clipboard data we have */
Packit 98cdb6
      _gtk_clipboard_store_all ();
Packit 98cdb6
Packit 98cdb6
      /* Synchronize the recent manager singleton */
Packit 98cdb6
      _gtk_recent_manager_sync ();
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_main_level (void)
Packit 98cdb6
{
Packit 98cdb6
  return gtk_main_loop_level;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_main_quit (void)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (main_loops != NULL);
Packit 98cdb6
Packit 98cdb6
  g_main_loop_quit (main_loops->data);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_events_pending (void)
Packit 98cdb6
{
Packit 98cdb6
  gboolean result;
Packit 98cdb6
  
Packit 98cdb6
  GDK_THREADS_LEAVE ();  
Packit 98cdb6
  result = g_main_context_pending (NULL);
Packit 98cdb6
  GDK_THREADS_ENTER ();
Packit 98cdb6
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_main_iteration (void)
Packit 98cdb6
{
Packit 98cdb6
  GDK_THREADS_LEAVE ();
Packit 98cdb6
  g_main_context_iteration (NULL, TRUE);
Packit 98cdb6
  GDK_THREADS_ENTER ();
Packit 98cdb6
Packit 98cdb6
  if (main_loops)
Packit 98cdb6
    return !g_main_loop_is_running (main_loops->data);
Packit 98cdb6
  else
Packit 98cdb6
    return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_main_iteration_do (gboolean blocking)
Packit 98cdb6
{
Packit 98cdb6
  GDK_THREADS_LEAVE ();
Packit 98cdb6
  g_main_context_iteration (NULL, blocking);
Packit 98cdb6
  GDK_THREADS_ENTER ();
Packit 98cdb6
Packit 98cdb6
  if (main_loops)
Packit 98cdb6
    return !g_main_loop_is_running (main_loops->data);
Packit 98cdb6
  else
Packit 98cdb6
    return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* private libgtk to libgdk interfaces
Packit 98cdb6
 */
Packit 98cdb6
gboolean gdk_pointer_grab_info_libgtk_only  (GdkDisplay *display,
Packit 98cdb6
					     GdkWindow **grab_window,
Packit 98cdb6
					     gboolean   *owner_events);
Packit 98cdb6
gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
Packit 98cdb6
					     GdkWindow **grab_window,
Packit 98cdb6
					     gboolean   *owner_events);
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rewrite_events_translate (GdkWindow *old_window,
Packit 98cdb6
			  GdkWindow *new_window,
Packit 98cdb6
			  gdouble   *x,
Packit 98cdb6
			  gdouble   *y)
Packit 98cdb6
{
Packit 98cdb6
  gint old_origin_x, old_origin_y;
Packit 98cdb6
  gint new_origin_x, new_origin_y;
Packit 98cdb6
Packit 98cdb6
  gdk_window_get_origin	(old_window, &old_origin_x, &old_origin_y);
Packit 98cdb6
  gdk_window_get_origin	(new_window, &new_origin_x, &new_origin_y);
Packit 98cdb6
Packit 98cdb6
  *x += old_origin_x - new_origin_x;
Packit 98cdb6
  *y += old_origin_y - new_origin_y;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkEvent *
Packit 98cdb6
rewrite_event_for_window (GdkEvent  *event,
Packit 98cdb6
			  GdkWindow *new_window)
Packit 98cdb6
{
Packit 98cdb6
  event = gdk_event_copy (event);
Packit 98cdb6
Packit 98cdb6
  switch (event->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_SCROLL:
Packit 98cdb6
      rewrite_events_translate (event->any.window,
Packit 98cdb6
				new_window,
Packit 98cdb6
				&event->scroll.x, &event->scroll.y);
Packit 98cdb6
      break;
Packit 98cdb6
    case GDK_BUTTON_PRESS:
Packit 98cdb6
    case GDK_2BUTTON_PRESS:
Packit 98cdb6
    case GDK_3BUTTON_PRESS:
Packit 98cdb6
    case GDK_BUTTON_RELEASE:
Packit 98cdb6
      rewrite_events_translate (event->any.window,
Packit 98cdb6
				new_window,
Packit 98cdb6
				&event->button.x, &event->button.y);
Packit 98cdb6
      break;
Packit 98cdb6
    case GDK_MOTION_NOTIFY:
Packit 98cdb6
      rewrite_events_translate (event->any.window,
Packit 98cdb6
				new_window,
Packit 98cdb6
				&event->motion.x, &event->motion.y);
Packit 98cdb6
      break;
Packit 98cdb6
    case GDK_KEY_PRESS:
Packit 98cdb6
    case GDK_KEY_RELEASE:
Packit 98cdb6
    case GDK_PROXIMITY_IN:
Packit 98cdb6
    case GDK_PROXIMITY_OUT:
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      return event;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_object_unref (event->any.window);
Packit 98cdb6
  event->any.window = g_object_ref (new_window);
Packit 98cdb6
Packit 98cdb6
  return event;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
Packit 98cdb6
 * then what X11 does is deliver the event normally if it was going to this
Packit 98cdb6
 * client, otherwise, delivers it in terms of the grab window. This function
Packit 98cdb6
 * rewrites events to the effect that events going to the same window group
Packit 98cdb6
 * are delivered normally, otherwise, the event is delivered in terms of the
Packit 98cdb6
 * grab window.
Packit 98cdb6
 */
Packit 98cdb6
static GdkEvent *
Packit 98cdb6
rewrite_event_for_grabs (GdkEvent *event)
Packit 98cdb6
{
Packit 98cdb6
  GdkWindow *grab_window;
Packit 98cdb6
  GtkWidget *event_widget, *grab_widget;
Packit 98cdb6
  gpointer grab_widget_ptr;
Packit 98cdb6
  gboolean owner_events;
Packit 98cdb6
  GdkDisplay *display;
Packit 98cdb6
Packit 98cdb6
  switch (event->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_SCROLL:
Packit 98cdb6
    case GDK_BUTTON_PRESS:
Packit 98cdb6
    case GDK_2BUTTON_PRESS:
Packit 98cdb6
    case GDK_3BUTTON_PRESS:
Packit 98cdb6
    case GDK_BUTTON_RELEASE:
Packit 98cdb6
    case GDK_MOTION_NOTIFY:
Packit 98cdb6
    case GDK_PROXIMITY_IN:
Packit 98cdb6
    case GDK_PROXIMITY_OUT:
Packit 98cdb6
      display = gdk_window_get_display (event->proximity.window);
Packit 98cdb6
      if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
Packit 98cdb6
	  !owner_events)
Packit 98cdb6
	return NULL;
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_KEY_PRESS:
Packit 98cdb6
    case GDK_KEY_RELEASE:
Packit 98cdb6
      display = gdk_window_get_display (event->key.window);
Packit 98cdb6
      if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
Packit 98cdb6
	  !owner_events)
Packit 98cdb6
	return NULL;
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      return NULL;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  event_widget = gtk_get_event_widget (event);
Packit 98cdb6
  gdk_window_get_user_data (grab_window, &grab_widget_ptr);
Packit 98cdb6
  grab_widget = grab_widget_ptr;
Packit 98cdb6
Packit 98cdb6
  if (grab_widget &&
Packit 98cdb6
      gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
Packit 98cdb6
    return rewrite_event_for_window (event, grab_window);
Packit 98cdb6
  else
Packit 98cdb6
    return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void 
Packit 98cdb6
gtk_main_do_event (GdkEvent *event)
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *event_widget;
Packit 98cdb6
  GtkWidget *grab_widget;
Packit 98cdb6
  GtkWindowGroup *window_group;
Packit 98cdb6
  GdkEvent *rewritten_event = NULL;
Packit 98cdb6
  GList *tmp_list;
Packit 98cdb6
Packit 98cdb6
  if (event->type == GDK_SETTING)
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_settings_handle_event (&event->setting);
Packit 98cdb6
      return;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (event->type == GDK_OWNER_CHANGE)
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_clipboard_handle_event (&event->owner_change);
Packit 98cdb6
      return;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* Find the widget which got the event. We store the widget
Packit 98cdb6
   *  in the user_data field of GdkWindow's.
Packit 98cdb6
   *  Ignore the event if we don't have a widget for it, except
Packit 98cdb6
   *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
Packit 98cdb6
   *  Though this happens rarely, bogus events can occour
Packit 98cdb6
   *  for e.g. destroyed GdkWindows. 
Packit 98cdb6
   */
Packit 98cdb6
  event_widget = gtk_get_event_widget (event);
Packit 98cdb6
  if (!event_widget)
Packit 98cdb6
    {
Packit 98cdb6
      /* To handle selection INCR transactions, we select
Packit 98cdb6
       * PropertyNotify events on the requestor window and create
Packit 98cdb6
       * a corresponding (fake) GdkWindow so that events get
Packit 98cdb6
       * here. There won't be a widget though, so we have to handle
Packit 98cdb6
	   * them specially
Packit 98cdb6
	   */
Packit 98cdb6
      if (event->type == GDK_PROPERTY_NOTIFY)
Packit 98cdb6
	_gtk_selection_incr_event (event->any.window,
Packit 98cdb6
				   &event->property);
Packit 98cdb6
Packit 98cdb6
      return;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* If pointer or keyboard grabs are in effect, munge the events
Packit 98cdb6
   * so that each window group looks like a separate app.
Packit 98cdb6
   */
Packit 98cdb6
  rewritten_event = rewrite_event_for_grabs (event);
Packit 98cdb6
  if (rewritten_event)
Packit 98cdb6
    {
Packit 98cdb6
      event = rewritten_event;
Packit 98cdb6
      event_widget = gtk_get_event_widget (event);
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  window_group = gtk_main_get_window_group (event_widget);
Packit 98cdb6
Packit 98cdb6
  /* Push the event onto a stack of current events for
Packit 98cdb6
   * gtk_current_event_get().
Packit 98cdb6
   */
Packit 98cdb6
  current_events = g_list_prepend (current_events, event);
Packit 98cdb6
Packit 98cdb6
  /* If there is a grab in effect...
Packit 98cdb6
   */
Packit 98cdb6
  if (window_group->grabs)
Packit 98cdb6
    {
Packit 98cdb6
      grab_widget = window_group->grabs->data;
Packit 98cdb6
      
Packit 98cdb6
      /* If the grab widget is an ancestor of the event widget
Packit 98cdb6
       *  then we send the event to the original event widget.
Packit 98cdb6
       *  This is the key to implementing modality.
Packit 98cdb6
       */
Packit 98cdb6
      if ((gtk_widget_is_sensitive (event_widget) || event->type == GDK_SCROLL) &&
Packit 98cdb6
	  gtk_widget_is_ancestor (event_widget, grab_widget))
Packit 98cdb6
	grab_widget = event_widget;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      grab_widget = event_widget;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* Not all events get sent to the grabbing widget.
Packit 98cdb6
   * The delete, destroy, expose, focus change and resize
Packit 98cdb6
   *  events still get sent to the event widget because
Packit 98cdb6
   *  1) these events have no meaning for the grabbing widget
Packit 98cdb6
   *  and 2) redirecting these events to the grabbing widget
Packit 98cdb6
   *  could cause the display to be messed up.
Packit 98cdb6
   * 
Packit 98cdb6
   * Drag events are also not redirected, since it isn't
Packit 98cdb6
   *  clear what the semantics of that would be.
Packit 98cdb6
   */
Packit 98cdb6
  switch (event->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_NOTHING:
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_DELETE:
Packit 98cdb6
      g_object_ref (event_widget);
Packit 98cdb6
      if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
Packit 98cdb6
	  !gtk_widget_event (event_widget, event))
Packit 98cdb6
	gtk_widget_destroy (event_widget);
Packit 98cdb6
      g_object_unref (event_widget);
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_DESTROY:
Packit 98cdb6
      /* Unexpected GDK_DESTROY from the outside, ignore for
Packit 98cdb6
       * child windows, handle like a GDK_DELETE for toplevels
Packit 98cdb6
       */
Packit 98cdb6
      if (!event_widget->parent)
Packit 98cdb6
	{
Packit 98cdb6
	  g_object_ref (event_widget);
Packit 98cdb6
	  if (!gtk_widget_event (event_widget, event) &&
Packit 98cdb6
	      gtk_widget_get_realized (event_widget))
Packit 98cdb6
	    gtk_widget_destroy (event_widget);
Packit 98cdb6
	  g_object_unref (event_widget);
Packit 98cdb6
	}
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_EXPOSE:
Packit 98cdb6
      if (event->any.window && gtk_widget_get_double_buffered (event_widget))
Packit 98cdb6
	{
Packit 98cdb6
	  gdk_window_begin_paint_region (event->any.window, event->expose.region);
Packit 98cdb6
	  gtk_widget_send_expose (event_widget, event);
Packit 98cdb6
	  gdk_window_end_paint (event->any.window);
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  /* The app may paint with a previously allocated cairo_t,
Packit 98cdb6
	     which will draw directly to the window. We can't catch cairo
Packit 98cdb6
	     drap operatoins to automatically flush the window, thus we
Packit 98cdb6
	     need to explicitly flush any outstanding moves or double
Packit 98cdb6
	     buffering */
Packit 98cdb6
	  gdk_window_flush (event->any.window);
Packit 98cdb6
	  gtk_widget_send_expose (event_widget, event);
Packit 98cdb6
	}
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_PROPERTY_NOTIFY:
Packit 98cdb6
    case GDK_NO_EXPOSE:
Packit 98cdb6
    case GDK_FOCUS_CHANGE:
Packit 98cdb6
    case GDK_CONFIGURE:
Packit 98cdb6
    case GDK_MAP:
Packit 98cdb6
    case GDK_UNMAP:
Packit 98cdb6
    case GDK_SELECTION_CLEAR:
Packit 98cdb6
    case GDK_SELECTION_REQUEST:
Packit 98cdb6
    case GDK_SELECTION_NOTIFY:
Packit 98cdb6
    case GDK_CLIENT_EVENT:
Packit 98cdb6
    case GDK_VISIBILITY_NOTIFY:
Packit 98cdb6
    case GDK_WINDOW_STATE:
Packit 98cdb6
    case GDK_GRAB_BROKEN:
Packit 98cdb6
    case GDK_DAMAGE:
Packit 98cdb6
      gtk_widget_event (event_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_SCROLL:
Packit 98cdb6
    case GDK_BUTTON_PRESS:
Packit 98cdb6
    case GDK_2BUTTON_PRESS:
Packit 98cdb6
    case GDK_3BUTTON_PRESS:
Packit 98cdb6
      gtk_propagate_event (grab_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_KEY_PRESS:
Packit 98cdb6
    case GDK_KEY_RELEASE:
Packit 98cdb6
      if (key_snoopers)
Packit 98cdb6
	{
Packit 98cdb6
	  if (gtk_invoke_key_snoopers (grab_widget, event))
Packit 98cdb6
	    break;
Packit 98cdb6
	}
Packit 98cdb6
      /* Catch alt press to enable auto-mnemonics;
Packit 98cdb6
       * menus are handled elsewhere
Packit 98cdb6
       */
Packit 98cdb6
      if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
Packit 98cdb6
          !GTK_IS_MENU_SHELL (grab_widget))
Packit 98cdb6
        {
Packit 98cdb6
          gboolean auto_mnemonics;
Packit 98cdb6
Packit 98cdb6
          g_object_get (gtk_widget_get_settings (grab_widget),
Packit 98cdb6
                        "gtk-auto-mnemonics", &auto_mnemonics, NULL);
Packit 98cdb6
Packit 98cdb6
          if (auto_mnemonics)
Packit 98cdb6
            {
Packit 98cdb6
              gboolean mnemonics_visible;
Packit 98cdb6
              GtkWidget *window;
Packit 98cdb6
Packit 98cdb6
              mnemonics_visible = (event->type == GDK_KEY_PRESS);
Packit 98cdb6
Packit 98cdb6
              window = gtk_widget_get_toplevel (grab_widget);
Packit 98cdb6
Packit 98cdb6
              if (GTK_IS_WINDOW (window))
Packit 98cdb6
                gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
Packit 98cdb6
            }
Packit 98cdb6
        }
Packit 98cdb6
      /* else fall through */
Packit 98cdb6
    case GDK_MOTION_NOTIFY:
Packit 98cdb6
    case GDK_BUTTON_RELEASE:
Packit 98cdb6
    case GDK_PROXIMITY_IN:
Packit 98cdb6
    case GDK_PROXIMITY_OUT:
Packit 98cdb6
      gtk_propagate_event (grab_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_ENTER_NOTIFY:
Packit 98cdb6
      GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
Packit 98cdb6
      _gtk_widget_set_pointer_window (event_widget, event->any.window);
Packit 98cdb6
      if (gtk_widget_is_sensitive (grab_widget))
Packit 98cdb6
	gtk_widget_event (grab_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_LEAVE_NOTIFY:
Packit 98cdb6
      GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
Packit 98cdb6
      if (gtk_widget_is_sensitive (grab_widget))
Packit 98cdb6
	gtk_widget_event (grab_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_DRAG_STATUS:
Packit 98cdb6
    case GDK_DROP_FINISHED:
Packit 98cdb6
      _gtk_drag_source_handle_event (event_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
    case GDK_DRAG_ENTER:
Packit 98cdb6
    case GDK_DRAG_LEAVE:
Packit 98cdb6
    case GDK_DRAG_MOTION:
Packit 98cdb6
    case GDK_DROP_START:
Packit 98cdb6
      _gtk_drag_dest_handle_event (event_widget, event);
Packit 98cdb6
      break;
Packit 98cdb6
    default:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (event->type == GDK_ENTER_NOTIFY
Packit 98cdb6
      || event->type == GDK_LEAVE_NOTIFY
Packit 98cdb6
      || event->type == GDK_BUTTON_PRESS
Packit 98cdb6
      || event->type == GDK_2BUTTON_PRESS
Packit 98cdb6
      || event->type == GDK_3BUTTON_PRESS
Packit 98cdb6
      || event->type == GDK_KEY_PRESS
Packit 98cdb6
      || event->type == GDK_DRAG_ENTER
Packit 98cdb6
      || event->type == GDK_GRAB_BROKEN
Packit 98cdb6
      || event->type == GDK_MOTION_NOTIFY
Packit 98cdb6
      || event->type == GDK_SCROLL)
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_tooltip_handle_event (event);
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  tmp_list = current_events;
Packit 98cdb6
  current_events = g_list_remove_link (current_events, tmp_list);
Packit 98cdb6
  g_list_free_1 (tmp_list);
Packit 98cdb6
Packit 98cdb6
  if (rewritten_event)
Packit 98cdb6
    gdk_event_free (rewritten_event);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_true (void)
Packit 98cdb6
{
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_false (void)
Packit 98cdb6
{
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkWindowGroup *
Packit 98cdb6
gtk_main_get_window_group (GtkWidget   *widget)
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *toplevel = NULL;
Packit 98cdb6
Packit 98cdb6
  if (widget)
Packit 98cdb6
    toplevel = gtk_widget_get_toplevel (widget);
Packit 98cdb6
Packit 98cdb6
  if (GTK_IS_WINDOW (toplevel))
Packit 98cdb6
    return gtk_window_get_group (GTK_WINDOW (toplevel));
Packit 98cdb6
  else
Packit 98cdb6
    return gtk_window_get_group (NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
typedef struct
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *old_grab_widget;
Packit 98cdb6
  GtkWidget *new_grab_widget;
Packit 98cdb6
  gboolean   was_grabbed;
Packit 98cdb6
  gboolean   is_grabbed;
Packit 98cdb6
  gboolean   from_grab;
Packit 98cdb6
} GrabNotifyInfo;
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_grab_notify_foreach (GtkWidget *child,
Packit 98cdb6
			 gpointer   data)
Packit 98cdb6
                        
Packit 98cdb6
{
Packit 98cdb6
  GrabNotifyInfo *info = data;
Packit 98cdb6
 
Packit 98cdb6
  gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
Packit 98cdb6
Packit 98cdb6
  was_grabbed = info->was_grabbed;
Packit 98cdb6
  is_grabbed = info->is_grabbed;
Packit 98cdb6
Packit 98cdb6
  info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
Packit 98cdb6
  info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
Packit 98cdb6
Packit 98cdb6
  was_shadowed = info->old_grab_widget && !info->was_grabbed;
Packit 98cdb6
  is_shadowed = info->new_grab_widget && !info->is_grabbed;
Packit 98cdb6
Packit 98cdb6
  g_object_ref (child);
Packit 98cdb6
Packit 98cdb6
  if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
Packit 98cdb6
    gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
Packit 98cdb6
  
Packit 98cdb6
  if (is_shadowed)
Packit 98cdb6
    {
Packit 98cdb6
      GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
Packit 98cdb6
      if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
Packit 98cdb6
	  && gtk_widget_is_sensitive (child))
Packit 98cdb6
	_gtk_widget_synthesize_crossing (child, info->new_grab_widget,
Packit 98cdb6
					 GDK_CROSSING_GTK_GRAB);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
Packit 98cdb6
      if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
Packit 98cdb6
	  && gtk_widget_is_sensitive (child))
Packit 98cdb6
	_gtk_widget_synthesize_crossing (info->old_grab_widget, child,
Packit 98cdb6
					 info->from_grab ? GDK_CROSSING_GTK_GRAB
Packit 98cdb6
					 : GDK_CROSSING_GTK_UNGRAB);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (was_shadowed != is_shadowed)
Packit 98cdb6
    _gtk_widget_grab_notify (child, was_shadowed);
Packit 98cdb6
  
Packit 98cdb6
  g_object_unref (child);
Packit 98cdb6
  
Packit 98cdb6
  info->was_grabbed = was_grabbed;
Packit 98cdb6
  info->is_grabbed = is_grabbed;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_grab_notify (GtkWindowGroup *group,
Packit 98cdb6
		 GtkWidget      *old_grab_widget,
Packit 98cdb6
		 GtkWidget      *new_grab_widget,
Packit 98cdb6
		 gboolean        from_grab)
Packit 98cdb6
{
Packit 98cdb6
  GList *toplevels;
Packit 98cdb6
  GrabNotifyInfo info;
Packit 98cdb6
Packit 98cdb6
  if (old_grab_widget == new_grab_widget)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  info.old_grab_widget = old_grab_widget;
Packit 98cdb6
  info.new_grab_widget = new_grab_widget;
Packit 98cdb6
  info.from_grab = from_grab;
Packit 98cdb6
Packit 98cdb6
  g_object_ref (group);
Packit 98cdb6
Packit 98cdb6
  toplevels = gtk_window_list_toplevels ();
Packit 98cdb6
  g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
Packit 98cdb6
			    
Packit 98cdb6
  while (toplevels)
Packit 98cdb6
    {
Packit 98cdb6
      GtkWindow *toplevel = toplevels->data;
Packit 98cdb6
      toplevels = g_list_delete_link (toplevels, toplevels);
Packit 98cdb6
Packit 98cdb6
      info.was_grabbed = FALSE;
Packit 98cdb6
      info.is_grabbed = FALSE;
Packit 98cdb6
Packit 98cdb6
      if (group == gtk_window_get_group (toplevel))
Packit 98cdb6
	gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info;;
Packit 98cdb6
      g_object_unref (toplevel);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_object_unref (group);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_grab_add (GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  GtkWindowGroup *group;
Packit 98cdb6
  GtkWidget *old_grab_widget;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (widget != NULL);
Packit 98cdb6
  
Packit 98cdb6
  if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_widget_set_has_grab (widget, TRUE);
Packit 98cdb6
      
Packit 98cdb6
      group = gtk_main_get_window_group (widget);
Packit 98cdb6
Packit 98cdb6
      if (group->grabs)
Packit 98cdb6
	old_grab_widget = (GtkWidget *)group->grabs->data;
Packit 98cdb6
      else
Packit 98cdb6
	old_grab_widget = NULL;
Packit 98cdb6
Packit 98cdb6
      g_object_ref (widget);
Packit 98cdb6
      group->grabs = g_slist_prepend (group->grabs, widget);
Packit 98cdb6
Packit 98cdb6
      gtk_grab_notify (group, old_grab_widget, widget, TRUE);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_grab_get_current:
Packit 98cdb6
 *
Packit 98cdb6
 * Queries the current grab of the default window group.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: (transfer none): The widget which currently
Packit 98cdb6
 *     has the grab or %NULL if no grab is active
Packit 98cdb6
 */
Packit 98cdb6
GtkWidget*
Packit 98cdb6
gtk_grab_get_current (void)
Packit 98cdb6
{
Packit 98cdb6
  GtkWindowGroup *group;
Packit 98cdb6
Packit 98cdb6
  group = gtk_main_get_window_group (NULL);
Packit 98cdb6
Packit 98cdb6
  if (group->grabs)
Packit 98cdb6
    return GTK_WIDGET (group->grabs->data);
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_grab_remove (GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  GtkWindowGroup *group;
Packit 98cdb6
  GtkWidget *new_grab_widget;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (widget != NULL);
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_widget_has_grab (widget))
Packit 98cdb6
    {
Packit 98cdb6
      _gtk_widget_set_has_grab (widget, FALSE);
Packit 98cdb6
Packit 98cdb6
      group = gtk_main_get_window_group (widget);
Packit 98cdb6
      group->grabs = g_slist_remove (group->grabs, widget);
Packit 98cdb6
      
Packit 98cdb6
      if (group->grabs)
Packit 98cdb6
	new_grab_widget = (GtkWidget *)group->grabs->data;
Packit 98cdb6
      else
Packit 98cdb6
	new_grab_widget = NULL;
Packit 98cdb6
Packit 98cdb6
      gtk_grab_notify (group, widget, new_grab_widget, FALSE);
Packit 98cdb6
      
Packit 98cdb6
      g_object_unref (widget);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_init_add (GtkFunction function,
Packit 98cdb6
	      gpointer	  data)
Packit 98cdb6
{
Packit 98cdb6
  GtkInitFunction *init;
Packit 98cdb6
  
Packit 98cdb6
  init = g_new (GtkInitFunction, 1);
Packit 98cdb6
  init->function = function;
Packit 98cdb6
  init->data = data;
Packit 98cdb6
  
Packit 98cdb6
  init_functions = g_list_prepend (init_functions, init);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_key_snooper_install (GtkKeySnoopFunc snooper,
Packit 98cdb6
			 gpointer	 func_data)
Packit 98cdb6
{
Packit 98cdb6
  GtkKeySnooperData *data;
Packit 98cdb6
  static guint snooper_id = 1;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (snooper != NULL, 0);
Packit 98cdb6
Packit 98cdb6
  data = g_new (GtkKeySnooperData, 1);
Packit 98cdb6
  data->func = snooper;
Packit 98cdb6
  data->func_data = func_data;
Packit 98cdb6
  data->id = snooper_id++;
Packit 98cdb6
  key_snoopers = g_slist_prepend (key_snoopers, data);
Packit 98cdb6
Packit 98cdb6
  return data->id;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_key_snooper_remove (guint snooper_id)
Packit 98cdb6
{
Packit 98cdb6
  GtkKeySnooperData *data = NULL;
Packit 98cdb6
  GSList *slist;
Packit 98cdb6
Packit 98cdb6
  slist = key_snoopers;
Packit 98cdb6
  while (slist)
Packit 98cdb6
    {
Packit 98cdb6
      data = slist->data;
Packit 98cdb6
      if (data->id == snooper_id)
Packit 98cdb6
	break;
Packit 98cdb6
Packit 98cdb6
      slist = slist->next;
Packit 98cdb6
      data = NULL;
Packit 98cdb6
    }
Packit 98cdb6
  if (data)
Packit 98cdb6
    {
Packit 98cdb6
      key_snoopers = g_slist_remove (key_snoopers, data);
Packit 98cdb6
      g_free (data);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gtk_invoke_key_snoopers (GtkWidget *grab_widget,
Packit 98cdb6
			 GdkEvent  *event)
Packit 98cdb6
{
Packit 98cdb6
  GSList *slist;
Packit 98cdb6
  gint return_val = FALSE;
Packit 98cdb6
Packit 98cdb6
  slist = key_snoopers;
Packit 98cdb6
  while (slist && !return_val)
Packit 98cdb6
    {
Packit 98cdb6
      GtkKeySnooperData *data;
Packit 98cdb6
Packit 98cdb6
      data = slist->data;
Packit 98cdb6
      slist = slist->next;
Packit 98cdb6
      return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return return_val;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_quit_add_full (guint		main_level,
Packit 98cdb6
		   GtkFunction		function,
Packit 98cdb6
		   GtkCallbackMarshal	marshal,
Packit 98cdb6
		   gpointer		data,
Packit 98cdb6
		   GDestroyNotify	destroy)
Packit 98cdb6
{
Packit 98cdb6
  static guint quit_id = 1;
Packit 98cdb6
  GtkQuitFunction *quitf;
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
Packit 98cdb6
Packit 98cdb6
  quitf = g_slice_new (GtkQuitFunction);
Packit 98cdb6
  
Packit 98cdb6
  quitf->id = quit_id++;
Packit 98cdb6
  quitf->main_level = main_level;
Packit 98cdb6
  quitf->function = function;
Packit 98cdb6
  quitf->marshal = marshal;
Packit 98cdb6
  quitf->data = data;
Packit 98cdb6
  quitf->destroy = destroy;
Packit 98cdb6
Packit 98cdb6
  quit_functions = g_list_prepend (quit_functions, quitf);
Packit 98cdb6
  
Packit 98cdb6
  return quitf->id;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_quit_destroy (GtkQuitFunction *quitf)
Packit 98cdb6
{
Packit 98cdb6
  if (quitf->destroy)
Packit 98cdb6
    quitf->destroy (quitf->data);
Packit 98cdb6
  g_slice_free (GtkQuitFunction, quitf);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gtk_quit_destructor (GtkObject **object_p)
Packit 98cdb6
{
Packit 98cdb6
  if (*object_p)
Packit 98cdb6
    gtk_object_destroy (*object_p);
Packit 98cdb6
  g_free (object_p);
Packit 98cdb6
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_quit_add_destroy (guint              main_level,
Packit 98cdb6
		      GtkObject         *object)
Packit 98cdb6
{
Packit 98cdb6
  GtkObject **object_p;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (main_level > 0);
Packit 98cdb6
  g_return_if_fail (GTK_IS_OBJECT (object));
Packit 98cdb6
Packit 98cdb6
  object_p = g_new (GtkObject*, 1);
Packit 98cdb6
  *object_p = object;
Packit 98cdb6
  g_signal_connect (object,
Packit 98cdb6
		    "destroy",
Packit 98cdb6
		    G_CALLBACK (gtk_widget_destroyed),
Packit 98cdb6
		    object_p);
Packit 98cdb6
  gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_quit_add (guint	  main_level,
Packit 98cdb6
	      GtkFunction function,
Packit 98cdb6
	      gpointer	  data)
Packit 98cdb6
{
Packit 98cdb6
  return gtk_quit_add_full (main_level, function, NULL, data, NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_quit_remove (guint id)
Packit 98cdb6
{
Packit 98cdb6
  GtkQuitFunction *quitf;
Packit 98cdb6
  GList *tmp_list;
Packit 98cdb6
  
Packit 98cdb6
  tmp_list = quit_functions;
Packit 98cdb6
  while (tmp_list)
Packit 98cdb6
    {
Packit 98cdb6
      quitf = tmp_list->data;
Packit 98cdb6
      
Packit 98cdb6
      if (quitf->id == id)
Packit 98cdb6
	{
Packit 98cdb6
	  quit_functions = g_list_remove_link (quit_functions, tmp_list);
Packit 98cdb6
	  g_list_free (tmp_list);
Packit 98cdb6
	  gtk_quit_destroy (quitf);
Packit 98cdb6
	  
Packit 98cdb6
	  return;
Packit 98cdb6
	}
Packit 98cdb6
      
Packit 98cdb6
      tmp_list = tmp_list->next;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_quit_remove_by_data (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  GtkQuitFunction *quitf;
Packit 98cdb6
  GList *tmp_list;
Packit 98cdb6
  
Packit 98cdb6
  tmp_list = quit_functions;
Packit 98cdb6
  while (tmp_list)
Packit 98cdb6
    {
Packit 98cdb6
      quitf = tmp_list->data;
Packit 98cdb6
      
Packit 98cdb6
      if (quitf->data == data)
Packit 98cdb6
	{
Packit 98cdb6
	  quit_functions = g_list_remove_link (quit_functions, tmp_list);
Packit 98cdb6
	  g_list_free (tmp_list);
Packit 98cdb6
	  gtk_quit_destroy (quitf);
Packit 98cdb6
Packit 98cdb6
	  return;
Packit 98cdb6
	}
Packit 98cdb6
      
Packit 98cdb6
      tmp_list = tmp_list->next;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_timeout_add_full (guint32		 interval,
Packit 98cdb6
		      GtkFunction	 function,
Packit 98cdb6
		      GtkCallbackMarshal marshal,
Packit 98cdb6
		      gpointer		 data,
Packit 98cdb6
		      GDestroyNotify	 destroy)
Packit 98cdb6
{
Packit 98cdb6
  if (marshal)
Packit 98cdb6
    {
Packit 98cdb6
      GtkClosure *closure;
Packit 98cdb6
Packit 98cdb6
      closure = g_new (GtkClosure, 1);
Packit 98cdb6
      closure->marshal = marshal;
Packit 98cdb6
      closure->data = data;
Packit 98cdb6
      closure->destroy = destroy;
Packit 98cdb6
Packit 98cdb6
      return g_timeout_add_full (0, interval, 
Packit 98cdb6
				 gtk_invoke_idle_timeout,
Packit 98cdb6
				 closure,
Packit 98cdb6
				 gtk_destroy_closure);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return g_timeout_add_full (0, interval, function, data, destroy);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_timeout_add (guint32     interval,
Packit 98cdb6
		 GtkFunction function,
Packit 98cdb6
		 gpointer    data)
Packit 98cdb6
{
Packit 98cdb6
  return g_timeout_add_full (0, interval, function, data, NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_timeout_remove (guint tag)
Packit 98cdb6
{
Packit 98cdb6
  g_source_remove (tag);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_idle_add_full (gint			priority,
Packit 98cdb6
		   GtkFunction		function,
Packit 98cdb6
		   GtkCallbackMarshal	marshal,
Packit 98cdb6
		   gpointer		data,
Packit 98cdb6
		   GDestroyNotify	destroy)
Packit 98cdb6
{
Packit 98cdb6
  if (marshal)
Packit 98cdb6
    {
Packit 98cdb6
      GtkClosure *closure;
Packit 98cdb6
Packit 98cdb6
      closure = g_new (GtkClosure, 1);
Packit 98cdb6
      closure->marshal = marshal;
Packit 98cdb6
      closure->data = data;
Packit 98cdb6
      closure->destroy = destroy;
Packit 98cdb6
Packit 98cdb6
      return g_idle_add_full (priority,
Packit 98cdb6
			      gtk_invoke_idle_timeout,
Packit 98cdb6
			      closure,
Packit 98cdb6
			      gtk_destroy_closure);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return g_idle_add_full (priority, function, data, destroy);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_idle_add (GtkFunction function,
Packit 98cdb6
	      gpointer	  data)
Packit 98cdb6
{
Packit 98cdb6
  return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint	    
Packit 98cdb6
gtk_idle_add_priority (gint        priority,
Packit 98cdb6
		       GtkFunction function,
Packit 98cdb6
		       gpointer	   data)
Packit 98cdb6
{
Packit 98cdb6
  return g_idle_add_full (priority, function, data, NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_idle_remove (guint tag)
Packit 98cdb6
{
Packit 98cdb6
  g_source_remove (tag);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_idle_remove_by_data (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  if (!g_idle_remove_by_data (data))
Packit 98cdb6
    g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
guint
Packit 98cdb6
gtk_input_add_full (gint		source,
Packit 98cdb6
		    GdkInputCondition	condition,
Packit 98cdb6
		    GdkInputFunction	function,
Packit 98cdb6
		    GtkCallbackMarshal	marshal,
Packit 98cdb6
		    gpointer		data,
Packit 98cdb6
		    GDestroyNotify	destroy)
Packit 98cdb6
{
Packit 98cdb6
  if (marshal)
Packit 98cdb6
    {
Packit 98cdb6
      GtkClosure *closure;
Packit 98cdb6
Packit 98cdb6
      closure = g_new (GtkClosure, 1);
Packit 98cdb6
      closure->marshal = marshal;
Packit 98cdb6
      closure->data = data;
Packit 98cdb6
      closure->destroy = destroy;
Packit 98cdb6
Packit 98cdb6
      return gdk_input_add_full (source,
Packit 98cdb6
				 condition,
Packit 98cdb6
				 (GdkInputFunction) gtk_invoke_input,
Packit 98cdb6
				 closure,
Packit 98cdb6
				 (GDestroyNotify) gtk_destroy_closure);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return gdk_input_add_full (source, condition, function, data, destroy);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_input_remove (guint tag)
Packit 98cdb6
{
Packit 98cdb6
  g_source_remove (tag);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_destroy_closure (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  GtkClosure *closure = data;
Packit 98cdb6
Packit 98cdb6
  if (closure->destroy)
Packit 98cdb6
    (closure->destroy) (closure->data);
Packit 98cdb6
  g_free (closure);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
gtk_invoke_idle_timeout (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  GtkClosure *closure = data;
Packit 98cdb6
Packit 98cdb6
  GtkArg args[1];
Packit 98cdb6
  gint ret_val = FALSE;
Packit 98cdb6
  args[0].name = NULL;
Packit 98cdb6
  args[0].type = G_TYPE_BOOLEAN;
Packit 98cdb6
  args[0].d.pointer_data = &ret_val;
Packit 98cdb6
  closure->marshal (NULL, closure->data,  0, args);
Packit 98cdb6
  return ret_val;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_invoke_input (gpointer	    data,
Packit 98cdb6
		  gint		    source,
Packit 98cdb6
		  GdkInputCondition condition)
Packit 98cdb6
{
Packit 98cdb6
  GtkClosure *closure = data;
Packit 98cdb6
Packit 98cdb6
  GtkArg args[3];
Packit 98cdb6
  args[0].type = G_TYPE_INT;
Packit 98cdb6
  args[0].name = NULL;
Packit 98cdb6
  GTK_VALUE_INT (args[0]) = source;
Packit 98cdb6
  args[1].type = GDK_TYPE_INPUT_CONDITION;
Packit 98cdb6
  args[1].name = NULL;
Packit 98cdb6
  GTK_VALUE_FLAGS (args[1]) = condition;
Packit 98cdb6
  args[2].type = G_TYPE_NONE;
Packit 98cdb6
  args[2].name = NULL;
Packit 98cdb6
Packit 98cdb6
  closure->marshal (NULL, closure->data, 2, args);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_get_current_event:
Packit 98cdb6
 * 
Packit 98cdb6
 * Obtains a copy of the event currently being processed by GTK+.  For
Packit 98cdb6
 * example, if you get a "clicked" signal from #GtkButton, the current
Packit 98cdb6
 * event will be the #GdkEventButton that triggered the "clicked"
Packit 98cdb6
 * signal. The returned event must be freed with gdk_event_free().
Packit 98cdb6
 * If there is no current event, the function returns %NULL.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: (transfer full): a copy of the current event, or %NULL if no
Packit 98cdb6
 *     current event.
Packit 98cdb6
 **/
Packit 98cdb6
GdkEvent*
Packit 98cdb6
gtk_get_current_event (void)
Packit 98cdb6
{
Packit 98cdb6
  if (current_events)
Packit 98cdb6
    return gdk_event_copy (current_events->data);
Packit 98cdb6
  else
Packit 98cdb6
    return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_get_current_event_time:
Packit 98cdb6
 * 
Packit 98cdb6
 * If there is a current event and it has a timestamp, return that
Packit 98cdb6
 * timestamp, otherwise return %GDK_CURRENT_TIME.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
Packit 98cdb6
 **/
Packit 98cdb6
guint32
Packit 98cdb6
gtk_get_current_event_time (void)
Packit 98cdb6
{
Packit 98cdb6
  if (current_events)
Packit 98cdb6
    return gdk_event_get_time (current_events->data);
Packit 98cdb6
  else
Packit 98cdb6
    return GDK_CURRENT_TIME;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_get_current_event_state:
Packit 98cdb6
 * @state: (out): a location to store the state of the current event
Packit 98cdb6
 * 
Packit 98cdb6
 * If there is a current event and it has a state field, place
Packit 98cdb6
 * that state field in @state and return %TRUE, otherwise return
Packit 98cdb6
 * %FALSE.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE if there was a current event and it had a state field
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_get_current_event_state (GdkModifierType *state)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (state != NULL, FALSE);
Packit 98cdb6
  
Packit 98cdb6
  if (current_events)
Packit 98cdb6
    return gdk_event_get_state (current_events->data, state);
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      *state = 0;
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_get_event_widget:
Packit 98cdb6
 * @event: a #GdkEvent
Packit 98cdb6
 *
Packit 98cdb6
 * If @event is %NULL or the event was not associated with any widget,
Packit 98cdb6
 * returns %NULL, otherwise returns the widget that received the event
Packit 98cdb6
 * originally.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: (transfer none): the widget that originally
Packit 98cdb6
 *     received @event, or %NULL
Packit 98cdb6
 **/
Packit 98cdb6
GtkWidget*
Packit 98cdb6
gtk_get_event_widget (GdkEvent *event)
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *widget;
Packit 98cdb6
  gpointer widget_ptr;
Packit 98cdb6
Packit 98cdb6
  widget = NULL;
Packit 98cdb6
  if (event && event->any.window && 
Packit 98cdb6
      (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
Packit 98cdb6
    {
Packit 98cdb6
      gdk_window_get_user_data (event->any.window, &widget_ptr);
Packit 98cdb6
      widget = widget_ptr;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  return widget;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gtk_quit_invoke_function (GtkQuitFunction *quitf)
Packit 98cdb6
{
Packit 98cdb6
  if (!quitf->marshal)
Packit 98cdb6
    return quitf->function (quitf->data);
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      GtkArg args[1];
Packit 98cdb6
      gint ret_val = FALSE;
Packit 98cdb6
Packit 98cdb6
      args[0].name = NULL;
Packit 98cdb6
      args[0].type = G_TYPE_BOOLEAN;
Packit 98cdb6
      args[0].d.pointer_data = &ret_val;
Packit 98cdb6
      ((GtkCallbackMarshal) quitf->marshal) (NULL,
Packit 98cdb6
					     quitf->data,
Packit 98cdb6
					     0, args);
Packit 98cdb6
      return ret_val;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_propagate_event:
Packit 98cdb6
 * @widget: a #GtkWidget
Packit 98cdb6
 * @event: an event
Packit 98cdb6
 *
Packit 98cdb6
 * Sends an event to a widget, propagating the event to parent widgets
Packit 98cdb6
 * if the event remains unhandled. Events received by GTK+ from GDK
Packit 98cdb6
 * normally begin in gtk_main_do_event(). Depending on the type of
Packit 98cdb6
 * event, existence of modal dialogs, grabs, etc., the event may be
Packit 98cdb6
 * propagated; if so, this function is used. gtk_propagate_event()
Packit 98cdb6
 * calls gtk_widget_event() on each widget it decides to send the
Packit 98cdb6
 * event to.  So gtk_widget_event() is the lowest-level function; it
Packit 98cdb6
 * simply emits the "event" and possibly an event-specific signal on a
Packit 98cdb6
 * widget.  gtk_propagate_event() is a bit higher-level, and
Packit 98cdb6
 * gtk_main_do_event() is the highest level.
Packit 98cdb6
 *
Packit 98cdb6
 * All that said, you most likely don't want to use any of these
Packit 98cdb6
 * functions; synthesizing events is rarely needed. Consider asking on
Packit 98cdb6
 * the mailing list for better ways to achieve your goals. For
Packit 98cdb6
 * example, use gdk_window_invalidate_rect() or
Packit 98cdb6
 * gtk_widget_queue_draw() instead of making up expose events.
Packit 98cdb6
 * 
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_propagate_event (GtkWidget *widget,
Packit 98cdb6
		     GdkEvent  *event)
Packit 98cdb6
{
Packit 98cdb6
  gint handled_event;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (GTK_IS_WIDGET (widget));
Packit 98cdb6
  g_return_if_fail (event != NULL);
Packit 98cdb6
  
Packit 98cdb6
  handled_event = FALSE;
Packit 98cdb6
Packit 98cdb6
  g_object_ref (widget);
Packit 98cdb6
      
Packit 98cdb6
  if ((event->type == GDK_KEY_PRESS) ||
Packit 98cdb6
      (event->type == GDK_KEY_RELEASE))
Packit 98cdb6
    {
Packit 98cdb6
      /* Only send key events within Window widgets to the Window
Packit 98cdb6
       *  The Window widget will in turn pass the
Packit 98cdb6
       *  key event on to the currently focused widget
Packit 98cdb6
       *  for that window.
Packit 98cdb6
       */
Packit 98cdb6
      GtkWidget *window;
Packit 98cdb6
Packit 98cdb6
      window = gtk_widget_get_toplevel (widget);
Packit 98cdb6
      if (GTK_IS_WINDOW (window))
Packit 98cdb6
	{
Packit 98cdb6
	  /* If there is a grab within the window, give the grab widget
Packit 98cdb6
	   * a first crack at the key event
Packit 98cdb6
	   */
Packit 98cdb6
	  if (widget != window && gtk_widget_has_grab (widget))
Packit 98cdb6
	    handled_event = gtk_widget_event (widget, event);
Packit 98cdb6
	  
Packit 98cdb6
	  if (!handled_event)
Packit 98cdb6
	    {
Packit 98cdb6
	      window = gtk_widget_get_toplevel (widget);
Packit 98cdb6
	      if (GTK_IS_WINDOW (window))
Packit 98cdb6
		{
Packit 98cdb6
		  if (gtk_widget_is_sensitive (window))
Packit 98cdb6
		    gtk_widget_event (window, event);
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
		  
Packit 98cdb6
	  handled_event = TRUE; /* don't send to widget */
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  /* Other events get propagated up the widget tree
Packit 98cdb6
   *  so that parents can see the button and motion
Packit 98cdb6
   *  events of the children.
Packit 98cdb6
   */
Packit 98cdb6
  if (!handled_event)
Packit 98cdb6
    {
Packit 98cdb6
      while (TRUE)
Packit 98cdb6
	{
Packit 98cdb6
	  GtkWidget *tmp;
Packit 98cdb6
Packit 98cdb6
	  /* Scroll events are special cased here because it
Packit 98cdb6
	   * feels wrong when scrolling a GtkViewport, say,
Packit 98cdb6
	   * to have children of the viewport eat the scroll
Packit 98cdb6
	   * event
Packit 98cdb6
	   */
Packit 98cdb6
	  if (!gtk_widget_is_sensitive (widget))
Packit 98cdb6
	    handled_event = event->type != GDK_SCROLL;
Packit 98cdb6
	  else
Packit 98cdb6
	    handled_event = gtk_widget_event (widget, event);
Packit 98cdb6
	      
Packit 98cdb6
	  tmp = widget->parent;
Packit 98cdb6
	  g_object_unref (widget);
Packit 98cdb6
Packit 98cdb6
	  widget = tmp;
Packit 98cdb6
	  
Packit 98cdb6
	  if (!handled_event && widget)
Packit 98cdb6
	    g_object_ref (widget);
Packit 98cdb6
	  else
Packit 98cdb6
	    break;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    g_object_unref (widget);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#if 0
Packit 98cdb6
static void
Packit 98cdb6
gtk_error (gchar *str)
Packit 98cdb6
{
Packit 98cdb6
  gtk_print (str);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_warning (gchar *str)
Packit 98cdb6
{
Packit 98cdb6
  gtk_print (str);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_message (gchar *str)
Packit 98cdb6
{
Packit 98cdb6
  gtk_print (str);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_print (gchar *str)
Packit 98cdb6
{
Packit 98cdb6
  static GtkWidget *window = NULL;
Packit 98cdb6
  static GtkWidget *text;
Packit 98cdb6
  static int level = 0;
Packit 98cdb6
  GtkWidget *box1;
Packit 98cdb6
  GtkWidget *box2;
Packit 98cdb6
  GtkWidget *table;
Packit 98cdb6
  GtkWidget *hscrollbar;
Packit 98cdb6
  GtkWidget *vscrollbar;
Packit 98cdb6
  GtkWidget *separator;
Packit 98cdb6
  GtkWidget *button;
Packit 98cdb6
  
Packit 98cdb6
  if (level > 0)
Packit 98cdb6
    {
Packit 98cdb6
      fputs (str, stdout);
Packit 98cdb6
      fflush (stdout);
Packit 98cdb6
      return;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  if (!window)
Packit 98cdb6
    {
Packit 98cdb6
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 98cdb6
      
Packit 98cdb6
      gtk_signal_connect (GTK_OBJECT (window), "destroy",
Packit 98cdb6
			  G_CALLBACK (gtk_widget_destroyed),
Packit 98cdb6
			  &window);
Packit 98cdb6
      
Packit 98cdb6
      gtk_window_set_title (GTK_WINDOW (window), "Messages");
Packit 98cdb6
      
Packit 98cdb6
      box1 = gtk_vbox_new (FALSE, 0);
Packit 98cdb6
      gtk_container_add (GTK_CONTAINER (window), box1);
Packit 98cdb6
      gtk_widget_show (box1);
Packit 98cdb6
      
Packit 98cdb6
      
Packit 98cdb6
      box2 = gtk_vbox_new (FALSE, 10);
Packit 98cdb6
      gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
Packit 98cdb6
      gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
Packit 98cdb6
      gtk_widget_show (box2);
Packit 98cdb6
      
Packit 98cdb6
      
Packit 98cdb6
      table = gtk_table_new (2, 2, FALSE);
Packit 98cdb6
      gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
Packit 98cdb6
      gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
Packit 98cdb6
      gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
Packit 98cdb6
      gtk_widget_show (table);
Packit 98cdb6
      
Packit 98cdb6
      text = gtk_text_new (NULL, NULL);
Packit 98cdb6
      gtk_text_set_editable (GTK_TEXT (text), FALSE);
Packit 98cdb6
      gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
Packit 98cdb6
      gtk_widget_show (text);
Packit 98cdb6
      gtk_widget_realize (text);
Packit 98cdb6
      
Packit 98cdb6
      hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
Packit 98cdb6
      gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
Packit 98cdb6
			GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
Packit 98cdb6
      gtk_widget_show (hscrollbar);
Packit 98cdb6
      
Packit 98cdb6
      vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
Packit 98cdb6
      gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
Packit 98cdb6
			GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
Packit 98cdb6
      gtk_widget_show (vscrollbar);
Packit 98cdb6
      
Packit 98cdb6
      separator = gtk_hseparator_new ();
Packit 98cdb6
      gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
Packit 98cdb6
      gtk_widget_show (separator);
Packit 98cdb6
      
Packit 98cdb6
      
Packit 98cdb6
      box2 = gtk_vbox_new (FALSE, 10);
Packit 98cdb6
      gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
Packit 98cdb6
      gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
Packit 98cdb6
      gtk_widget_show (box2);
Packit 98cdb6
      
Packit 98cdb6
      
Packit 98cdb6
      button = gtk_button_new_with_label ("close");
Packit 98cdb6
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
Packit 98cdb6
				 G_CALLBACK (gtk_widget_hide),
Packit 98cdb6
				 GTK_OBJECT (window));
Packit 98cdb6
      gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
Packit 98cdb6
      gtk_widget_set_can_default (button, TRUE);
Packit 98cdb6
      gtk_widget_grab_default (button);
Packit 98cdb6
      gtk_widget_show (button);
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  level += 1;
Packit 98cdb6
  gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
Packit 98cdb6
  level -= 1;
Packit 98cdb6
  
Packit 98cdb6
  if (!gtk_widget_get_visible (window))
Packit 98cdb6
    gtk_widget_show (window);
Packit 98cdb6
}
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
_gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
Packit 98cdb6
				  GValue                *return_accu,
Packit 98cdb6
				  const GValue          *handler_return,
Packit 98cdb6
				  gpointer               dummy)
Packit 98cdb6
{
Packit 98cdb6
  gboolean continue_emission;
Packit 98cdb6
  gboolean signal_handled;
Packit 98cdb6
  
Packit 98cdb6
  signal_handled = g_value_get_boolean (handler_return);
Packit 98cdb6
  g_value_set_boolean (return_accu, signal_handled);
Packit 98cdb6
  continue_emission = !signal_handled;
Packit 98cdb6
  
Packit 98cdb6
  return continue_emission;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
_gtk_button_event_triggers_context_menu (GdkEventButton *event)
Packit 98cdb6
{
Packit 98cdb6
  if (event->type == GDK_BUTTON_PRESS)
Packit 98cdb6
    {
Packit 98cdb6
      if (event->button == 3 &&
Packit 98cdb6
          ! (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))
Packit 98cdb6
        return TRUE;
Packit 98cdb6
Packit 98cdb6
#ifdef GDK_WINDOWING_QUARTZ
Packit 98cdb6
      if (event->button == 1 &&
Packit 98cdb6
          ! (event->state & (GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) &&
Packit 98cdb6
          (event->state & GDK_CONTROL_MASK))
Packit 98cdb6
        return TRUE;
Packit 98cdb6
#endif
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
_gtk_translate_keyboard_accel_state (GdkKeymap       *keymap,
Packit 98cdb6
                                     guint            hardware_keycode,
Packit 98cdb6
                                     GdkModifierType  state,
Packit 98cdb6
                                     GdkModifierType  accel_mask,
Packit 98cdb6
                                     gint             group,
Packit 98cdb6
                                     guint           *keyval,
Packit 98cdb6
                                     gint            *effective_group,
Packit 98cdb6
                                     gint            *level,
Packit 98cdb6
                                     GdkModifierType *consumed_modifiers)
Packit 98cdb6
{
Packit 98cdb6
  gboolean group_mask_disabled = FALSE;
Packit 98cdb6
  gboolean retval;
Packit 98cdb6
Packit 98cdb6
  /* if the group-toggling modifier is part of the accel mod mask, and
Packit 98cdb6
   * it is active, disable it for matching
Packit 98cdb6
   */
Packit 98cdb6
  if (accel_mask & state & GTK_TOGGLE_GROUP_MOD_MASK)
Packit 98cdb6
    {
Packit 98cdb6
      state &= ~GTK_TOGGLE_GROUP_MOD_MASK;
Packit 98cdb6
      group = 0;
Packit 98cdb6
      group_mask_disabled = TRUE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  retval = gdk_keymap_translate_keyboard_state (keymap,
Packit 98cdb6
                                                hardware_keycode, state, group,
Packit 98cdb6
                                                keyval,
Packit 98cdb6
                                                effective_group, level,
Packit 98cdb6
                                                consumed_modifiers);
Packit 98cdb6
Packit 98cdb6
  /* add back the group mask, we want to match against the modifier,
Packit 98cdb6
   * but not against the keyval from its group
Packit 98cdb6
   */
Packit 98cdb6
  if (group_mask_disabled)
Packit 98cdb6
    {
Packit 98cdb6
      if (effective_group)
Packit 98cdb6
        *effective_group = 1;
Packit 98cdb6
Packit 98cdb6
      if (consumed_modifiers)
Packit 98cdb6
        *consumed_modifiers &= ~GTK_TOGGLE_GROUP_MOD_MASK;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return retval;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#define __GTK_MAIN_C__
Packit 98cdb6
#include "gtkaliasdef.c"