2008-07-01 22:57:50 +00:00
|
|
|
|
/* GTK - The GIMP Toolkit
|
1997-11-24 22:37:52 +00:00
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2000-07-26 11:33:08 +00:00
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
1997-11-24 22:37:52 +00:00
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2000-07-26 11:33:08 +00:00
|
|
|
|
* Lesser General Public License for more details.
|
1997-11-24 22:37:52 +00:00
|
|
|
|
*
|
2000-07-26 11:33:08 +00:00
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-02-27 13:01:10 +00:00
|
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
1997-11-24 22:37:52 +00:00
|
|
|
|
*/
|
1999-02-24 07:37:18 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2000-07-26 11:33:08 +00:00
|
|
|
|
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
1999-02-24 07:37:18 +00:00
|
|
|
|
* file for a list of people on the GTK+ Team. See the ChangeLog
|
|
|
|
|
* files for a list of changes. These files are distributed with
|
|
|
|
|
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
|
|
|
|
*/
|
|
|
|
|
|
2008-06-22 14:28:52 +00:00
|
|
|
|
#include "config.h"
|
2004-03-06 03:38:59 +00:00
|
|
|
|
|
2010-12-09 04:07:00 +00:00
|
|
|
|
#include "gdk/gdk.h"
|
2014-11-07 13:40:22 +00:00
|
|
|
|
#include "gdk/gdk-private.h"
|
2017-01-18 21:41:20 +00:00
|
|
|
|
#include "gsk/gskprivate.h"
|
2020-04-07 22:33:54 +00:00
|
|
|
|
#include "gsk/gskrendernodeprivate.h"
|
2020-06-07 12:48:14 +00:00
|
|
|
|
#include "gtknative.h"
|
2001-04-02 23:33:47 +00:00
|
|
|
|
|
This might seem like a large patch, but it isn't that bad, and nothing
should break on Unix/X11.
Win32 merge and general portability stuff:
* acconfig.h,configure.in: Check for <sys/time.h>.
* gdk/win32: New directory (actually, been there for a while).
* gtk/fnmatch.c: Include <glib.h> for G_DIR_SEPARATOR, WIN32 and
NATIVE_WIN32, and use these. Always case fold on Win32. No
backslashed escapes on native Win32.
* gtk/{gtk.def,makefile.msc}: New files.
* gtk/Makefile.am: Add above new files.
* gtk/{gtkaccelgroup,gtkbindings}.c: Include <string.h>
instead of <strings.h>.
* gtk/{gtkcalendar,gtkitemfactory,gtkpreview,gtkrc}.c: Include
config.h. Protect inclusion of <sys/param.h>, <sys/time.h>, and
<unistd.h> appropriately.
* gtk/gtkdnd.c: Merge in Win32 version (which doesn't do much).
Use ABS() (from <glib.h>) instead of abs().
* gtk/gtkfilesel.c: Moved Win32-specific includes after inclusion
of gtk (and thus glib) headers, so that WIN32 will be
defined. With MS C, include <direct.h> for mkdir prototype.
* gtk/gtkitemfactory.c (gtk_item_factory_callback_marshal): Add
some casts, needed by MS C.
* gtk/{gtklayout,gtkplug}.c: Merge in Win32 version (which isn't
implemented).
* gtk/gtkmain.c: Include gdk/gdkx.h for GDK_WINDOWING. Include
<X11/Xlocale.h> only on X11 platform, otherwise <locale.h>. Use
G_SEARCHPATH_SEPARATOR_S and g_module_build_path.
* gtk/gtkmain.h: Mark variables for export/import on Win32.
* gtk/gtkrange.c (gtk_range_motion_notify): Set mods also in case
the event is not a hint, or its window is not the slider. Needed
on Win32, at least.
* gtk/gtkrc.c: Include config.h and gdk/gdkx.h. Use <locale.h>
unless on X11. Skip \r chars, too. Use G_DIR_SEPARATOR and
G_SEARCHPATH_SEPARATOR(_S). Use g_path_is_absolute. On Win32, use
a subdirectory of the Windows directory as gtk system
configuration directory.
* gtk/gtkselection.c: No chunks on Win32.
* gtk/gtksocket.c: Not implemented on Win32.
* gtk/gtkthemes.c (gtk_theme_engine_get): Use g_module_build_path.
* gtk/makeenums.h: Include gdkprivate.h after gdk.h.
* gtk/testrgb.c: Use dynamically allocated buffer. Use GTimers.
1999-03-15 00:03:37 +00:00
|
|
|
|
#include <locale.h>
|
2000-11-16 00:41:02 +00:00
|
|
|
|
|
1997-11-24 22:37:52 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
1998-04-04 01:56:54 +00:00
|
|
|
|
#include <string.h>
|
2004-09-01 20:30:24 +00:00
|
|
|
|
#ifdef HAVE_UNISTD_H
|
2001-05-09 16:15:09 +00:00
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
2010-12-24 03:11:28 +00:00
|
|
|
|
#include <sys/types.h> /* For uid_t, gid_t */
|
2004-09-01 20:30:24 +00:00
|
|
|
|
|
Updates.
2001-10-29 Tor Lillqvist <tml@iki.fi>
* README.win32: Updates.
* gtk-zip.sh.in: New file, used to build distribution package for
Windows.
* gdk/gdkglobals.c: Mark gdk_threads_mutex for DLL export when
applicable with GDKVAR.
* gtk/gtk.def: Update.
* gtk/gtkfilesel.c: Include <winsock.h> (if available) for
gethostname().
* gtk/gtkmain.c
* gtk/gtkrc.c: (Win32) Save actual DLL name for later use in DLL
entry function. Avoid hardcoded paths GTK_LIBDIR, GTK_SYSCONFDIR,
GTK_DATA_PREFIX and GTK_LOCALEDIR, instead add functions that call
g_win32_get_package_installation_subdirectory() with the actual
DLL name saved above. Redefine above directory name macros to call
these functions. Remove some ifdefs.
* gtk/maketypes.awk: Output GTKTYPEBUILTINS_VAR (that marks
variable for export on Win32) also to the _vars file.
Changes for autoconfiscated build on Win32, and addition of Win32
backend to the related files:
* configure.in: Like in GLib, set LT_CURRENT_MINUS_AGE for use
when forming DLL name in some files. Set MS_LIB_AVAILABLE is
lib.exe is available. Call AC_LIBTOOL_WIN32_DLL. Set
PLATFORM_WIN32, OS_WIN32 and USE_WIN32 automake conditionals. Add
win32 target, using pangowin32. Don't use the
-export-symbols-regex option on Win32, we use .def files to list
exported symbols. Check <winsock.h> (for gethostname() in
gtkfilesel.c). Enclose nested AC_CHECK_* macros in brackets to
prevent premature m4 expansion.
* acconfig.h: Add HAVE_WINTAB.
* gdk/Makefile.am: Add libgdk-win32-1.3.la target and associated
macros and rules. Use -no-undefined on Win32. Use gdk.def file. If
MS_LIB_AVAILABLE, build MS import library. Install the import
libraries. If HAVE_WINTAB, link with the Wintab library.
* gtk/Makefile.am: Add libgtk-win32-1.3.la target and associated
macros and rules. Use -no-undefined on Win32. Use gtk-win32.def
file. Install import libraries.
2001-10-29 07:06:37 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
#define STRICT
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#undef STRICT
|
|
|
|
|
#endif
|
2001-09-11 20:24:40 +00:00
|
|
|
|
|
2003-01-12 04:44:23 +00:00
|
|
|
|
#include "gtkintl.h"
|
|
|
|
|
|
2002-04-18 11:21:21 +00:00
|
|
|
|
#include "gtkbox.h"
|
2011-10-23 11:57:07 +00:00
|
|
|
|
#include "gtkdebug.h"
|
2020-02-29 02:47:17 +00:00
|
|
|
|
#include "gtkdropprivate.h"
|
2011-10-23 11:57:07 +00:00
|
|
|
|
#include "gtkmain.h"
|
2018-03-01 20:46:16 +00:00
|
|
|
|
#include "gtkmediafileprivate.h"
|
2011-10-22 06:48:13 +00:00
|
|
|
|
#include "gtkmodulesprivate.h"
|
2011-10-23 11:57:07 +00:00
|
|
|
|
#include "gtkprivate.h"
|
2007-06-19 10:29:55 +00:00
|
|
|
|
#include "gtkrecentmanager.h"
|
2010-12-24 03:11:28 +00:00
|
|
|
|
#include "gtksettingsprivate.h"
|
2014-10-20 02:51:21 +00:00
|
|
|
|
#include "gtktooltipprivate.h"
|
2010-10-19 17:14:46 +00:00
|
|
|
|
#include "gtkwidgetprivate.h"
|
2010-12-18 01:41:16 +00:00
|
|
|
|
#include "gtkwindowprivate.h"
|
2014-06-04 10:18:03 +00:00
|
|
|
|
#include "gtkwindowgroup.h"
|
2019-05-26 21:57:23 +00:00
|
|
|
|
#include "gtkprintbackendprivate.h"
|
2021-02-17 20:25:42 +00:00
|
|
|
|
#include "gtkimmoduleprivate.h"
|
2019-02-23 21:53:19 +00:00
|
|
|
|
#include "gtkroot.h"
|
2019-05-26 18:02:55 +00:00
|
|
|
|
#include "gtknative.h"
|
2020-12-09 15:48:09 +00:00
|
|
|
|
#include "gtkpopcountprivate.h"
|
2007-11-28 01:06:07 +00:00
|
|
|
|
|
2019-02-24 04:06:00 +00:00
|
|
|
|
#include "inspector/window.h"
|
2011-10-22 06:48:13 +00:00
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
#define GDK_ARRAY_ELEMENT_TYPE GtkWidget *
|
|
|
|
|
#define GDK_ARRAY_TYPE_NAME GtkWidgetStack
|
|
|
|
|
#define GDK_ARRAY_NAME gtk_widget_stack
|
|
|
|
|
#define GDK_ARRAY_FREE_FUNC g_object_unref
|
|
|
|
|
#define GDK_ARRAY_PREALLOC 16
|
|
|
|
|
#include "gdk/gdkarrayimpl.c"
|
|
|
|
|
|
2001-06-14 21:44:01 +00:00
|
|
|
|
static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
|
|
|
|
|
|
2020-07-24 13:54:49 +00:00
|
|
|
|
static int pre_initialized = FALSE;
|
|
|
|
|
static int gtk_initialized = FALSE;
|
1997-12-18 02:17:14 +00:00
|
|
|
|
static GList *current_events = NULL;
|
1998-12-15 07:32:11 +00:00
|
|
|
|
|
2016-05-05 22:51:30 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
GdkDisplay *display;
|
|
|
|
|
guint flags;
|
|
|
|
|
} DisplayDebugFlags;
|
|
|
|
|
|
|
|
|
|
#define N_DEBUG_DISPLAYS 4
|
|
|
|
|
|
|
|
|
|
DisplayDebugFlags debug_flags[N_DEBUG_DISPLAYS];
|
2018-07-07 09:37:24 +00:00
|
|
|
|
/* This is a flag to speed up development builds. We set it to TRUE when
|
|
|
|
|
* any of the debug displays has debug flags >0, but we never set it back
|
|
|
|
|
* to FALSE. This way we don't need to call gtk_widget_get_display() in
|
|
|
|
|
* hot paths. */
|
|
|
|
|
gboolean any_display_debug_flags_set = FALSE;
|
1998-02-19 06:21:27 +00:00
|
|
|
|
|
2020-09-14 02:48:29 +00:00
|
|
|
|
GtkDebugFlags
|
|
|
|
|
gtk_get_display_debug_flags (GdkDisplay *display)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (display == NULL)
|
|
|
|
|
display = gdk_display_get_default ();
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < N_DEBUG_DISPLAYS; i++)
|
|
|
|
|
{
|
|
|
|
|
if (debug_flags[i].display == display)
|
|
|
|
|
return (GtkDebugFlags)debug_flags[i].flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
gtk_get_any_display_debug_flag_set (void)
|
|
|
|
|
{
|
|
|
|
|
return any_display_debug_flags_set;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gtk_set_display_debug_flags (GdkDisplay *display,
|
|
|
|
|
GtkDebugFlags flags)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < N_DEBUG_DISPLAYS; i++)
|
|
|
|
|
{
|
|
|
|
|
if (debug_flags[i].display == NULL)
|
|
|
|
|
debug_flags[i].display = display;
|
|
|
|
|
|
|
|
|
|
if (debug_flags[i].display == display)
|
|
|
|
|
{
|
|
|
|
|
debug_flags[i].flags = flags;
|
|
|
|
|
if (flags > 0)
|
|
|
|
|
any_display_debug_flags_set = TRUE;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_get_debug_flags:
|
|
|
|
|
*
|
|
|
|
|
* Returns the GTK debug flags that are currently active.
|
|
|
|
|
*
|
|
|
|
|
* This function is intended for GTK modules that want
|
|
|
|
|
* to adjust their debug output based on GTK debug flags.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the GTK debug flags.
|
|
|
|
|
*/
|
|
|
|
|
GtkDebugFlags
|
|
|
|
|
gtk_get_debug_flags (void)
|
|
|
|
|
{
|
|
|
|
|
if (gtk_get_any_display_debug_flag_set ())
|
|
|
|
|
return gtk_get_display_debug_flags (gdk_display_get_default ());
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_set_debug_flags:
|
|
|
|
|
* @flags: the debug flags to set
|
|
|
|
|
*
|
|
|
|
|
* Sets the GTK debug flags.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_set_debug_flags (GtkDebugFlags flags)
|
|
|
|
|
{
|
|
|
|
|
gtk_set_display_debug_flags (gdk_display_get_default (), flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
gtk_simulate_touchscreen (void)
|
|
|
|
|
{
|
|
|
|
|
return (gtk_get_debug_flags () & GTK_DEBUG_TOUCHSCREEN) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-28 03:11:07 +00:00
|
|
|
|
static const GdkDebugKey gtk_debug_keys[] = {
|
|
|
|
|
{ "keybindings", GTK_DEBUG_KEYBINDINGS, "Information about keyboard shortcuts" },
|
|
|
|
|
{ "modules", GTK_DEBUG_MODULES, "Information about modules and extensions" },
|
|
|
|
|
{ "icontheme", GTK_DEBUG_ICONTHEME, "Information about icon themes" },
|
|
|
|
|
{ "printing", GTK_DEBUG_PRINTING, "Information about printing" },
|
|
|
|
|
{ "geometry", GTK_DEBUG_GEOMETRY, "Information about size allocation" },
|
|
|
|
|
{ "size-request", GTK_DEBUG_SIZE_REQUEST, "Information about size requests" },
|
|
|
|
|
{ "actions", GTK_DEBUG_ACTIONS, "Information about actions and menu models" },
|
2020-07-20 01:03:17 +00:00
|
|
|
|
{ "constraints", GTK_DEBUG_CONSTRAINTS, "Information from the constraints solver" },
|
2020-06-28 03:11:07 +00:00
|
|
|
|
{ "text", GTK_DEBUG_TEXT, "Information about GtkTextView" },
|
|
|
|
|
{ "tree", GTK_DEBUG_TREE, "Information about GtkTreeView" },
|
2020-07-20 01:03:17 +00:00
|
|
|
|
{ "layout", GTK_DEBUG_LAYOUT, "Information from layout managers" },
|
2020-06-28 03:11:07 +00:00
|
|
|
|
{ "builder", GTK_DEBUG_BUILDER, "Trace GtkBuilder operation" },
|
|
|
|
|
{ "builder-objects", GTK_DEBUG_BUILDER_OBJECTS, "Log unused GtkBuilder objects" },
|
|
|
|
|
{ "no-css-cache", GTK_DEBUG_NO_CSS_CACHE, "Disable style property cache" },
|
2020-11-14 07:49:17 +00:00
|
|
|
|
{ "interactive", GTK_DEBUG_INTERACTIVE, "Enable the GTK inspector", TRUE },
|
2020-06-28 03:11:07 +00:00
|
|
|
|
{ "touchscreen", GTK_DEBUG_TOUCHSCREEN, "Pretend the pointer is a touchscreen" },
|
|
|
|
|
{ "snapshot", GTK_DEBUG_SNAPSHOT, "Generate debug render nodes" },
|
2020-07-17 14:36:20 +00:00
|
|
|
|
{ "accessibility", GTK_DEBUG_A11Y, "Information about accessibility state changes" },
|
2021-03-25 21:26:15 +00:00
|
|
|
|
{ "iconfallback", GTK_DEBUG_ICONFALLBACK, "Information about icon fallback" },
|
1998-02-19 06:21:27 +00:00
|
|
|
|
};
|
1997-11-24 22:37:52 +00:00
|
|
|
|
|
2001-02-13 04:56:07 +00:00
|
|
|
|
/* This checks to see if the process is running suid or sgid
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* at the current time. If so, we don’t allow GTK to be initialized.
|
2001-02-13 04:56:07 +00:00
|
|
|
|
* This is meant to be a mild check - we only error out if we
|
|
|
|
|
* can prove the programmer is doing something wrong, not if
|
|
|
|
|
* they could be doing something wrong. For this reason, we
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* don’t use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
|
2001-02-13 04:56:07 +00:00
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
check_setugid (void)
|
|
|
|
|
{
|
2001-08-24 20:09:26 +00:00
|
|
|
|
/* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
|
2001-02-19 21:54:04 +00:00
|
|
|
|
#ifndef G_OS_WIN32
|
2001-02-13 04:56:07 +00:00
|
|
|
|
uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
|
|
|
|
|
gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
|
2020-09-14 02:10:25 +00:00
|
|
|
|
|
2001-02-13 04:56:07 +00:00
|
|
|
|
#ifdef HAVE_GETRESUID
|
|
|
|
|
if (getresuid (&ruid, &euid, &suid) != 0 ||
|
|
|
|
|
getresgid (&rgid, &egid, &sgid) != 0)
|
|
|
|
|
#endif /* HAVE_GETRESUID */
|
|
|
|
|
{
|
|
|
|
|
suid = ruid = getuid ();
|
|
|
|
|
sgid = rgid = getgid ();
|
|
|
|
|
euid = geteuid ();
|
|
|
|
|
egid = getegid ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ruid != euid || ruid != suid ||
|
|
|
|
|
rgid != egid || rgid != sgid)
|
|
|
|
|
{
|
|
|
|
|
g_warning ("This process is currently running setuid or setgid.\n"
|
2019-04-05 05:07:32 +00:00
|
|
|
|
"This is not a supported use of GTK. You must create a helper\n"
|
2011-01-04 22:32:12 +00:00
|
|
|
|
"program instead. For further details, see:\n\n"
|
|
|
|
|
" http://www.gtk.org/setuid.html\n\n"
|
2019-04-05 05:07:32 +00:00
|
|
|
|
"Refusing to initialize GTK.");
|
2001-02-13 04:56:07 +00:00
|
|
|
|
exit (1);
|
|
|
|
|
}
|
2001-02-19 21:54:04 +00:00
|
|
|
|
#endif
|
2001-02-13 04:56:07 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-10 16:56:54 +00:00
|
|
|
|
static gboolean do_setlocale = TRUE;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_disable_setlocale:
|
2017-03-17 20:11:26 +00:00
|
|
|
|
*
|
2021-02-14 19:00:12 +00:00
|
|
|
|
* Prevents [id@gtk_init] and [id@gtk_init_check] from automatically calling
|
|
|
|
|
* `setlocale (LC_ALL, "")`.
|
|
|
|
|
*
|
|
|
|
|
* You would want to use this function if you wanted to set the locale for
|
2014-02-07 18:01:26 +00:00
|
|
|
|
* your program to something other than the user’s locale, or if
|
More precise documentation about underscores and mnemonics. (#66380)
* gtk/gtklabel.c (gtk_label_new_with_mnemonic),
gtk/gtkbutton.c (gtk_button_new_with_mnemonic): More precise
documentation about underscores and mnemonics. (#66380)
* gtk/gtktextiter.c (gtk_text_iter_backward_word_starts): Fix
cyclic reference in docs.
* gtk/gtklabel.c (gtk_label_set_justify): Correct documentation
of default value. (#65402)
* gtk/gtkmain.c (gtk_set_locale, gtk_disable_set_locale):
Markup fixes.
* gdk-pixbuf-io.c, gdk-pixbuf-animation.c, gdk-pixbuf-data.c,
gdk-pixbuf-loader.c, gdk-pixbuf-scale.c, gdk-pixbuf-util.c,
gdk-pixdata.c: Markup fixes.
* gtk/text_widget.sgml: More precise wording. (#63388)
* gtk/tmpl/gtksignal.sgml (GTK_SIGNAL_OFFSET): Add docs.
* gtk/resources.sgml: Fix markup of mail URLs.
* gtk/tmpl/gtkpaned.sgml, gtk/tmpl/gtkobject.sgml: Markup fixes.
* gtk/tmpl/gtktoolbar.sgml (gtk_toolbar_{prepend,append}_element):
Expand documentation. (#60471)
* gtk/tmpl/gtkmain.sgml: Remove misleading information about
gtk_set_locale(). (#65758)
2001-12-20 23:09:29 +00:00
|
|
|
|
* you wanted to set different values for different locale categories.
|
2001-10-10 16:56:54 +00:00
|
|
|
|
*
|
|
|
|
|
* Most programs should not need to call this function.
|
|
|
|
|
**/
|
2001-10-19 15:27:43 +00:00
|
|
|
|
void
|
2001-10-10 16:56:54 +00:00
|
|
|
|
gtk_disable_setlocale (void)
|
|
|
|
|
{
|
2007-02-16 06:09:02 +00:00
|
|
|
|
if (pre_initialized)
|
2001-10-10 16:56:54 +00:00
|
|
|
|
g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
|
2020-09-14 02:10:25 +00:00
|
|
|
|
|
2001-10-10 16:56:54 +00:00
|
|
|
|
do_setlocale = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-09 15:50:29 +00:00
|
|
|
|
#ifdef G_PLATFORM_WIN32
|
2002-04-18 11:21:21 +00:00
|
|
|
|
#undef gtk_init_check
|
2004-08-09 15:50:29 +00:00
|
|
|
|
#endif
|
2002-04-18 11:21:21 +00:00
|
|
|
|
|
2006-10-10 21:51:11 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
|
|
|
|
|
static char *iso639_to_check = NULL;
|
|
|
|
|
static char *iso3166_to_check = NULL;
|
|
|
|
|
static char *script_to_check = NULL;
|
|
|
|
|
static gboolean setlocale_called = FALSE;
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK
|
|
|
|
|
enum_locale_proc (LPTSTR locale)
|
|
|
|
|
{
|
|
|
|
|
LCID lcid;
|
|
|
|
|
char iso639[10];
|
|
|
|
|
char iso3166[10];
|
|
|
|
|
char *endptr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lcid = strtoul (locale, &endptr, 16);
|
|
|
|
|
if (*endptr == '\0' &&
|
|
|
|
|
GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
|
|
|
|
|
GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (iso639, iso639_to_check) == 0 &&
|
2011-01-04 22:32:12 +00:00
|
|
|
|
((iso3166_to_check != NULL &&
|
|
|
|
|
strcmp (iso3166, iso3166_to_check) == 0) ||
|
|
|
|
|
(iso3166_to_check == NULL &&
|
|
|
|
|
SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
|
|
|
|
|
{
|
|
|
|
|
char language[100], country[100];
|
|
|
|
|
|
|
|
|
|
if (script_to_check != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* If lcid is the "other" script for this language,
|
|
|
|
|
* return TRUE, i.e. continue looking.
|
|
|
|
|
*/
|
|
|
|
|
if (strcmp (script_to_check, "Latn") == 0)
|
|
|
|
|
{
|
|
|
|
|
switch (LANGIDFROMLCID (lcid))
|
|
|
|
|
{
|
|
|
|
|
case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
|
|
|
|
|
return TRUE;
|
|
|
|
|
case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
|
|
|
|
|
return TRUE;
|
|
|
|
|
case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
|
|
|
|
|
return TRUE;
|
|
|
|
|
case MAKELANGID (LANG_SERBIAN, 0x07):
|
|
|
|
|
/* Serbian in Bosnia and Herzegovina, Cyrillic */
|
|
|
|
|
return TRUE;
|
2018-06-10 21:02:56 +00:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp (script_to_check, "Cyrl") == 0)
|
|
|
|
|
{
|
|
|
|
|
switch (LANGIDFROMLCID (lcid))
|
|
|
|
|
{
|
|
|
|
|
case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
|
|
|
|
|
return TRUE;
|
|
|
|
|
case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
|
|
|
|
|
return TRUE;
|
|
|
|
|
case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
|
|
|
|
|
return TRUE;
|
|
|
|
|
case MAKELANGID (LANG_SERBIAN, 0x06):
|
|
|
|
|
/* Serbian in Bosnia and Herzegovina, Latin */
|
|
|
|
|
return TRUE;
|
2018-06-10 21:02:56 +00:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetThreadLocale (lcid);
|
|
|
|
|
|
|
|
|
|
if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
|
|
|
|
|
GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
|
|
|
|
|
{
|
2019-05-21 05:15:16 +00:00
|
|
|
|
char str[300];
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2019-05-21 05:15:16 +00:00
|
|
|
|
strcpy (str, language);
|
|
|
|
|
strcat (str, "_");
|
|
|
|
|
strcat (str, country);
|
|
|
|
|
|
|
|
|
|
if (setlocale (LC_ALL, str) != NULL)
|
2011-01-04 22:32:12 +00:00
|
|
|
|
setlocale_called = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2006-10-10 21:51:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
Make gtk argument parsing use goption. Add gtk_get_option_group and
2004-09-05 Anders Carlsson <andersca@gnome.org>
* gdk/gdk.c: (gdk_arg_class_cb), (gdk_arg_name_cb),
(gdk_add_option_entries_libgtk_only), (gdk_pre_parse_libgtk_only),
(gdk_parse_args):
* gdk/gdk.h:
* gdk/gdkinternals.h:
* gdk/linux-fb/gdkmain-fb.c: (_gdk_windowing_init):
* gdk/win32/gdkmain-win32.c: (_gdk_windowing_init):
* gdk/x11/gdkdisplay-x11.c: (gdk_display_open):
* gdk/x11/gdkmain-x11.c: (_gdk_windowing_init):
* gtk/gtkmain.c: (gtk_arg_debug_cb), (gtk_arg_no_debug_cb),
(gtk_arg_module_cb), (gtk_arg_warnings_cb),
(do_pre_parse_initialization), (do_post_parse_initialization),
(pre_parse_hook), (post_parse_hook), (gtk_get_option_group),
(gtk_init_with_args), (gtk_parse_args):
* gtk/gtkmain.h:
Make gtk argument parsing use goption. Add gtk_get_option_group and
gtk_init_with_args.
* tests/testtreemodel.c: (main):
Use gtk_init_with_args.
2004-09-05 15:09:55 +00:00
|
|
|
|
static void
|
2008-06-11 23:40:35 +00:00
|
|
|
|
setlocale_initialization (void)
|
Make gtk argument parsing use goption. Add gtk_get_option_group and
2004-09-05 Anders Carlsson <andersca@gnome.org>
* gdk/gdk.c: (gdk_arg_class_cb), (gdk_arg_name_cb),
(gdk_add_option_entries_libgtk_only), (gdk_pre_parse_libgtk_only),
(gdk_parse_args):
* gdk/gdk.h:
* gdk/gdkinternals.h:
* gdk/linux-fb/gdkmain-fb.c: (_gdk_windowing_init):
* gdk/win32/gdkmain-win32.c: (_gdk_windowing_init):
* gdk/x11/gdkdisplay-x11.c: (gdk_display_open):
* gdk/x11/gdkmain-x11.c: (_gdk_windowing_init):
* gtk/gtkmain.c: (gtk_arg_debug_cb), (gtk_arg_no_debug_cb),
(gtk_arg_module_cb), (gtk_arg_warnings_cb),
(do_pre_parse_initialization), (do_post_parse_initialization),
(pre_parse_hook), (post_parse_hook), (gtk_get_option_group),
(gtk_init_with_args), (gtk_parse_args):
* gtk/gtkmain.h:
Make gtk argument parsing use goption. Add gtk_get_option_group and
gtk_init_with_args.
* tests/testtreemodel.c: (main):
Use gtk_init_with_args.
2004-09-05 15:09:55 +00:00
|
|
|
|
{
|
2008-06-11 23:40:35 +00:00
|
|
|
|
static gboolean initialized = FALSE;
|
2001-10-10 16:56:54 +00:00
|
|
|
|
|
2008-06-11 23:40:35 +00:00
|
|
|
|
if (initialized)
|
2007-02-16 06:09:02 +00:00
|
|
|
|
return;
|
2008-06-11 23:40:35 +00:00
|
|
|
|
initialized = TRUE;
|
2007-02-16 06:09:02 +00:00
|
|
|
|
|
2001-10-10 16:56:54 +00:00
|
|
|
|
if (do_setlocale)
|
2002-02-13 17:48:01 +00:00
|
|
|
|
{
|
2006-10-10 21:51:11 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
/* If some of the POSIXish environment variables are set, set
|
|
|
|
|
* the Win32 thread locale correspondingly.
|
|
|
|
|
*/
|
|
|
|
|
char *p = getenv ("LC_ALL");
|
|
|
|
|
if (p == NULL)
|
2011-01-04 22:32:12 +00:00
|
|
|
|
p = getenv ("LANG");
|
2006-10-10 21:51:11 +00:00
|
|
|
|
|
|
|
|
|
if (p != NULL)
|
2011-01-04 22:32:12 +00:00
|
|
|
|
{
|
|
|
|
|
p = g_strdup (p);
|
|
|
|
|
if (strcmp (p, "C") == 0)
|
|
|
|
|
SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Check if one of the supported locales match the
|
|
|
|
|
* environment variable. If so, use that locale.
|
|
|
|
|
*/
|
|
|
|
|
iso639_to_check = p;
|
|
|
|
|
iso3166_to_check = strchr (iso639_to_check, '_');
|
|
|
|
|
if (iso3166_to_check != NULL)
|
|
|
|
|
{
|
|
|
|
|
*iso3166_to_check++ = '\0';
|
|
|
|
|
|
|
|
|
|
script_to_check = strchr (iso3166_to_check, '@');
|
|
|
|
|
if (script_to_check != NULL)
|
|
|
|
|
*script_to_check++ = '\0';
|
|
|
|
|
|
|
|
|
|
/* Handle special cases. */
|
|
|
|
|
|
|
|
|
|
/* The standard code for Serbia and Montenegro was
|
|
|
|
|
* "CS", but MSFT uses for some reason "SP". By now
|
|
|
|
|
* (October 2006), SP has split into two, "RS" and
|
|
|
|
|
* "ME", but don't bother trying to handle those
|
|
|
|
|
* yet. Do handle the even older "YU", though.
|
|
|
|
|
*/
|
|
|
|
|
if (strcmp (iso3166_to_check, "CS") == 0 ||
|
|
|
|
|
strcmp (iso3166_to_check, "YU") == 0)
|
2018-06-10 21:02:56 +00:00
|
|
|
|
iso3166_to_check = (char *) "SP";
|
2011-01-04 22:32:12 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
script_to_check = strchr (iso639_to_check, '@');
|
|
|
|
|
if (script_to_check != NULL)
|
|
|
|
|
*script_to_check++ = '\0';
|
|
|
|
|
/* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
|
|
|
|
|
if (strcmp (iso639_to_check, "sr") == 0)
|
2018-06-10 21:02:56 +00:00
|
|
|
|
iso3166_to_check = (char *) "SP";
|
2011-01-04 22:32:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
|
|
|
|
|
}
|
|
|
|
|
g_free (p);
|
|
|
|
|
}
|
2006-10-10 21:51:11 +00:00
|
|
|
|
if (!setlocale_called)
|
2011-01-04 22:32:12 +00:00
|
|
|
|
setlocale (LC_ALL, "");
|
2006-10-10 21:51:11 +00:00
|
|
|
|
#else
|
2002-02-13 17:48:01 +00:00
|
|
|
|
if (!setlocale (LC_ALL, ""))
|
2011-01-04 22:32:12 +00:00
|
|
|
|
g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
|
2006-10-10 21:51:11 +00:00
|
|
|
|
#endif
|
2002-02-13 17:48:01 +00:00
|
|
|
|
}
|
2008-06-11 23:40:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 14:31:22 +00:00
|
|
|
|
/* Return TRUE if module_to_check causes version conflicts.
|
|
|
|
|
* If module_to_check is NULL, check the main module.
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
_gtk_module_has_mixed_deps (GModule *module_to_check)
|
|
|
|
|
{
|
|
|
|
|
GModule *module;
|
|
|
|
|
gpointer func;
|
|
|
|
|
gboolean result;
|
|
|
|
|
|
|
|
|
|
if (!module_to_check)
|
|
|
|
|
module = g_module_open (NULL, 0);
|
|
|
|
|
else
|
|
|
|
|
module = module_to_check;
|
|
|
|
|
|
|
|
|
|
if (g_module_symbol (module, "gtk_progress_get_type", &func))
|
|
|
|
|
result = TRUE;
|
|
|
|
|
else if (g_module_symbol (module, "gtk_misc_get_type", &func))
|
|
|
|
|
result = TRUE;
|
|
|
|
|
else
|
|
|
|
|
result = FALSE;
|
|
|
|
|
|
|
|
|
|
if (!module_to_check)
|
|
|
|
|
g_module_close (module);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-11 23:40:35 +00:00
|
|
|
|
static void
|
2016-12-28 13:49:37 +00:00
|
|
|
|
do_pre_parse_initialization (void)
|
2008-06-11 23:40:35 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *env_string;
|
2016-03-14 10:38:23 +00:00
|
|
|
|
double slowdown;
|
2016-12-28 13:49:37 +00:00
|
|
|
|
|
2008-06-11 23:40:35 +00:00
|
|
|
|
if (pre_initialized)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pre_initialized = TRUE;
|
1998-12-15 07:32:11 +00:00
|
|
|
|
|
2011-02-08 18:49:16 +00:00
|
|
|
|
if (_gtk_module_has_mixed_deps (NULL))
|
2019-04-05 05:07:32 +00:00
|
|
|
|
g_error ("GTK 2/3 symbols detected. Using GTK 2/3 and GTK 4 in the same process is not supported");
|
2010-06-19 02:27:26 +00:00
|
|
|
|
|
2016-11-24 00:31:16 +00:00
|
|
|
|
gdk_pre_parse ();
|
2011-02-08 18:49:16 +00:00
|
|
|
|
|
2020-06-28 03:11:07 +00:00
|
|
|
|
debug_flags[0].flags = gdk_parse_debug_var ("GTK_DEBUG",
|
|
|
|
|
gtk_debug_keys,
|
|
|
|
|
G_N_ELEMENTS (gtk_debug_keys));
|
|
|
|
|
any_display_debug_flags_set = debug_flags[0].flags > 0;
|
1998-02-19 18:02:03 +00:00
|
|
|
|
|
2016-03-14 10:38:23 +00:00
|
|
|
|
env_string = g_getenv ("GTK_SLOWDOWN");
|
|
|
|
|
if (env_string)
|
|
|
|
|
{
|
|
|
|
|
slowdown = g_ascii_strtod (env_string, NULL);
|
|
|
|
|
_gtk_set_slowdown (slowdown);
|
|
|
|
|
}
|
2020-08-19 18:20:41 +00:00
|
|
|
|
|
|
|
|
|
/* Trigger fontconfig initialization early */
|
|
|
|
|
pango_cairo_font_map_get_default ();
|
Make gtk argument parsing use goption. Add gtk_get_option_group and
2004-09-05 Anders Carlsson <andersca@gnome.org>
* gdk/gdk.c: (gdk_arg_class_cb), (gdk_arg_name_cb),
(gdk_add_option_entries_libgtk_only), (gdk_pre_parse_libgtk_only),
(gdk_parse_args):
* gdk/gdk.h:
* gdk/gdkinternals.h:
* gdk/linux-fb/gdkmain-fb.c: (_gdk_windowing_init):
* gdk/win32/gdkmain-win32.c: (_gdk_windowing_init):
* gdk/x11/gdkdisplay-x11.c: (gdk_display_open):
* gdk/x11/gdkmain-x11.c: (_gdk_windowing_init):
* gtk/gtkmain.c: (gtk_arg_debug_cb), (gtk_arg_no_debug_cb),
(gtk_arg_module_cb), (gtk_arg_warnings_cb),
(do_pre_parse_initialization), (do_post_parse_initialization),
(pre_parse_hook), (post_parse_hook), (gtk_get_option_group),
(gtk_init_with_args), (gtk_parse_args):
* gtk/gtkmain.h:
Make gtk argument parsing use goption. Add gtk_get_option_group and
gtk_init_with_args.
* tests/testtreemodel.c: (main):
Use gtk_init_with_args.
2004-09-05 15:09:55 +00:00
|
|
|
|
}
|
1998-10-25 19:30:02 +00:00
|
|
|
|
|
2005-08-01 13:52:29 +00:00
|
|
|
|
static void
|
|
|
|
|
gettext_initialization (void)
|
|
|
|
|
{
|
2008-06-11 23:40:35 +00:00
|
|
|
|
setlocale_initialization ();
|
|
|
|
|
|
2005-08-01 13:52:29 +00:00
|
|
|
|
#ifdef ENABLE_NLS
|
2011-10-22 06:48:13 +00:00
|
|
|
|
bindtextdomain (GETTEXT_PACKAGE, _gtk_get_localedir ());
|
|
|
|
|
bindtextdomain (GETTEXT_PACKAGE "-properties", _gtk_get_localedir ());
|
2005-08-01 13:52:29 +00:00
|
|
|
|
# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
|
|
|
|
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
|
|
|
|
bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
|
|
|
|
|
# endif
|
2016-12-28 13:49:37 +00:00
|
|
|
|
#endif
|
2005-08-01 13:52:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-09 04:16:39 +00:00
|
|
|
|
static void
|
|
|
|
|
default_display_notify_cb (GdkDisplayManager *dm)
|
|
|
|
|
{
|
2018-03-06 23:57:16 +00:00
|
|
|
|
debug_flags[0].display = gdk_display_get_default ();
|
2015-01-09 04:16:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
Make gtk argument parsing use goption. Add gtk_get_option_group and
2004-09-05 Anders Carlsson <andersca@gnome.org>
* gdk/gdk.c: (gdk_arg_class_cb), (gdk_arg_name_cb),
(gdk_add_option_entries_libgtk_only), (gdk_pre_parse_libgtk_only),
(gdk_parse_args):
* gdk/gdk.h:
* gdk/gdkinternals.h:
* gdk/linux-fb/gdkmain-fb.c: (_gdk_windowing_init):
* gdk/win32/gdkmain-win32.c: (_gdk_windowing_init):
* gdk/x11/gdkdisplay-x11.c: (gdk_display_open):
* gdk/x11/gdkmain-x11.c: (_gdk_windowing_init):
* gtk/gtkmain.c: (gtk_arg_debug_cb), (gtk_arg_no_debug_cb),
(gtk_arg_module_cb), (gtk_arg_warnings_cb),
(do_pre_parse_initialization), (do_post_parse_initialization),
(pre_parse_hook), (post_parse_hook), (gtk_get_option_group),
(gtk_init_with_args), (gtk_parse_args):
* gtk/gtkmain.h:
Make gtk argument parsing use goption. Add gtk_get_option_group and
gtk_init_with_args.
* tests/testtreemodel.c: (main):
Use gtk_init_with_args.
2004-09-05 15:09:55 +00:00
|
|
|
|
static void
|
2016-12-28 13:49:37 +00:00
|
|
|
|
do_post_parse_initialization (void)
|
Make gtk argument parsing use goption. Add gtk_get_option_group and
2004-09-05 Anders Carlsson <andersca@gnome.org>
* gdk/gdk.c: (gdk_arg_class_cb), (gdk_arg_name_cb),
(gdk_add_option_entries_libgtk_only), (gdk_pre_parse_libgtk_only),
(gdk_parse_args):
* gdk/gdk.h:
* gdk/gdkinternals.h:
* gdk/linux-fb/gdkmain-fb.c: (_gdk_windowing_init):
* gdk/win32/gdkmain-win32.c: (_gdk_windowing_init):
* gdk/x11/gdkdisplay-x11.c: (gdk_display_open):
* gdk/x11/gdkmain-x11.c: (_gdk_windowing_init):
* gtk/gtkmain.c: (gtk_arg_debug_cb), (gtk_arg_no_debug_cb),
(gtk_arg_module_cb), (gtk_arg_warnings_cb),
(do_pre_parse_initialization), (do_post_parse_initialization),
(pre_parse_hook), (post_parse_hook), (gtk_get_option_group),
(gtk_init_with_args), (gtk_parse_args):
* gtk/gtkmain.h:
Make gtk argument parsing use goption. Add gtk_get_option_group and
gtk_init_with_args.
* tests/testtreemodel.c: (main):
Use gtk_init_with_args.
2004-09-05 15:09:55 +00:00
|
|
|
|
{
|
2015-10-06 22:00:35 +00:00
|
|
|
|
GdkDisplayManager *display_manager;
|
|
|
|
|
|
2005-05-02 13:41:32 +00:00
|
|
|
|
if (gtk_initialized)
|
|
|
|
|
return;
|
|
|
|
|
|
2005-08-01 13:52:29 +00:00
|
|
|
|
gettext_initialization ();
|
|
|
|
|
|
2009-10-06 11:53:22 +00:00
|
|
|
|
#ifdef SIGPIPE
|
2009-10-01 15:41:17 +00:00
|
|
|
|
signal (SIGPIPE, SIG_IGN);
|
2009-10-06 11:53:22 +00:00
|
|
|
|
#endif
|
2009-10-01 15:41:17 +00:00
|
|
|
|
|
2013-12-10 21:27:24 +00:00
|
|
|
|
gtk_widget_set_default_direction (gtk_get_locale_direction ());
|
2000-10-22 13:00:13 +00:00
|
|
|
|
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
gdk_event_init_types ();
|
2017-01-18 21:41:20 +00:00
|
|
|
|
gsk_ensure_resources ();
|
2020-04-07 22:33:54 +00:00
|
|
|
|
gsk_render_node_init_types ();
|
2013-03-24 08:16:20 +00:00
|
|
|
|
_gtk_ensure_resources ();
|
2012-01-12 18:14:33 +00:00
|
|
|
|
|
1998-06-10 07:32:52 +00:00
|
|
|
|
gtk_initialized = TRUE;
|
1998-08-17 02:41:42 +00:00
|
|
|
|
|
2019-05-27 12:59:36 +00:00
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
|
gtk_print_backends_init ();
|
|
|
|
|
#endif
|
|
|
|
|
gtk_im_modules_init ();
|
|
|
|
|
gtk_media_file_extension_init ();
|
|
|
|
|
|
2015-10-06 22:00:35 +00:00
|
|
|
|
display_manager = gdk_display_manager_get ();
|
|
|
|
|
if (gdk_display_manager_get_default_display (display_manager) != NULL)
|
2018-02-18 09:34:52 +00:00
|
|
|
|
default_display_notify_cb (display_manager);
|
2015-10-06 22:00:35 +00:00
|
|
|
|
|
|
|
|
|
g_signal_connect (display_manager, "notify::default-display",
|
2015-01-09 04:16:39 +00:00
|
|
|
|
G_CALLBACK (default_display_notify_cb),
|
|
|
|
|
NULL);
|
Make gtk argument parsing use goption. Add gtk_get_option_group and
2004-09-05 Anders Carlsson <andersca@gnome.org>
* gdk/gdk.c: (gdk_arg_class_cb), (gdk_arg_name_cb),
(gdk_add_option_entries_libgtk_only), (gdk_pre_parse_libgtk_only),
(gdk_parse_args):
* gdk/gdk.h:
* gdk/gdkinternals.h:
* gdk/linux-fb/gdkmain-fb.c: (_gdk_windowing_init):
* gdk/win32/gdkmain-win32.c: (_gdk_windowing_init):
* gdk/x11/gdkdisplay-x11.c: (gdk_display_open):
* gdk/x11/gdkmain-x11.c: (_gdk_windowing_init):
* gtk/gtkmain.c: (gtk_arg_debug_cb), (gtk_arg_no_debug_cb),
(gtk_arg_module_cb), (gtk_arg_warnings_cb),
(do_pre_parse_initialization), (do_post_parse_initialization),
(pre_parse_hook), (post_parse_hook), (gtk_get_option_group),
(gtk_init_with_args), (gtk_parse_args):
* gtk/gtkmain.h:
Make gtk argument parsing use goption. Add gtk_get_option_group and
gtk_init_with_args.
* tests/testtreemodel.c: (main):
Use gtk_init_with_args.
2004-09-05 15:09:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-08-09 15:50:29 +00:00
|
|
|
|
#ifdef G_PLATFORM_WIN32
|
2002-06-20 23:29:19 +00:00
|
|
|
|
#undef gtk_init_check
|
2004-08-09 15:50:29 +00:00
|
|
|
|
#endif
|
2002-06-20 23:29:19 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_init_check:
|
2009-12-10 10:23:40 +00:00
|
|
|
|
*
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* This function does the same work as gtk_init() with only a single
|
|
|
|
|
* change: It does not terminate the program if the windowing system
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* can’t be initialized. Instead it returns %FALSE on failure.
|
2002-06-20 23:29:19 +00:00
|
|
|
|
*
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* This way the application can fall back to some other means of
|
|
|
|
|
* communication with the user - for example a curses or command line
|
|
|
|
|
* interface.
|
|
|
|
|
*
|
2014-02-19 23:49:43 +00:00
|
|
|
|
* Returns: %TRUE if the windowing system has been successfully
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* initialized, %FALSE otherwise
|
|
|
|
|
*/
|
2002-06-20 23:29:19 +00:00
|
|
|
|
gboolean
|
2016-12-28 13:49:37 +00:00
|
|
|
|
gtk_init_check (void)
|
2002-06-20 23:29:19 +00:00
|
|
|
|
{
|
2014-05-10 17:22:17 +00:00
|
|
|
|
gboolean ret;
|
|
|
|
|
|
2016-12-28 12:46:56 +00:00
|
|
|
|
if (gtk_initialized)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
gettext_initialization ();
|
|
|
|
|
|
|
|
|
|
if (!check_setugid ())
|
2002-06-20 23:29:19 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
2016-12-28 13:49:37 +00:00
|
|
|
|
do_pre_parse_initialization ();
|
|
|
|
|
do_post_parse_initialization ();
|
2016-12-28 12:46:56 +00:00
|
|
|
|
|
2016-11-24 00:31:16 +00:00
|
|
|
|
ret = gdk_display_open_default () != NULL;
|
2014-05-10 17:22:17 +00:00
|
|
|
|
|
2018-03-11 12:14:14 +00:00
|
|
|
|
if (ret && (gtk_get_debug_flags () & GTK_DEBUG_INTERACTIVE))
|
2014-05-10 17:22:17 +00:00
|
|
|
|
gtk_window_set_interactive_debugging (TRUE);
|
|
|
|
|
|
|
|
|
|
return ret;
|
2002-06-20 23:29:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-08-09 15:50:29 +00:00
|
|
|
|
#ifdef G_PLATFORM_WIN32
|
2000-08-19 21:46:05 +00:00
|
|
|
|
#undef gtk_init
|
2004-08-09 15:50:29 +00:00
|
|
|
|
#endif
|
2000-08-19 21:46:05 +00:00
|
|
|
|
|
2002-06-20 23:29:19 +00:00
|
|
|
|
/**
|
2002-08-07 22:23:18 +00:00
|
|
|
|
* gtk_init:
|
2009-12-10 10:23:40 +00:00
|
|
|
|
*
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* Call this function before using any other GTK functions in your GUI
|
2009-12-10 10:23:40 +00:00
|
|
|
|
* applications. It will initialize everything needed to operate the
|
2011-01-04 16:18:42 +00:00
|
|
|
|
* toolkit and parses some standard command line options.
|
2004-11-05 07:18:28 +00:00
|
|
|
|
*
|
2016-12-28 13:49:37 +00:00
|
|
|
|
* If you are using #GtkApplication, you don't have to call gtk_init()
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* or gtk_init_check(); the #GApplication::startup handler
|
2014-05-13 02:58:47 +00:00
|
|
|
|
* does it for you.
|
|
|
|
|
*
|
2011-01-04 16:18:42 +00:00
|
|
|
|
* This function will terminate your program if it was unable to
|
|
|
|
|
* initialize the windowing system for some reason. If you want
|
|
|
|
|
* your program to fall back to a textual interface you want to
|
|
|
|
|
* call gtk_init_check() instead.
|
2009-10-01 15:41:17 +00:00
|
|
|
|
*
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* GTK calls `signal (SIGPIPE, SIG_IGN)`
|
2009-10-01 15:41:17 +00:00
|
|
|
|
* during initialization, to ignore SIGPIPE signals, since these are
|
|
|
|
|
* almost never wanted in graphical applications. If you do need to
|
|
|
|
|
* handle SIGPIPE for some reason, reset the handler after gtk_init(),
|
|
|
|
|
* but notice that other libraries (e.g. libdbus or gvfs) might do
|
|
|
|
|
* similar things.
|
2011-01-04 16:18:42 +00:00
|
|
|
|
*/
|
1999-02-21 20:55:04 +00:00
|
|
|
|
void
|
2016-12-28 13:49:37 +00:00
|
|
|
|
gtk_init (void)
|
1999-02-21 20:55:04 +00:00
|
|
|
|
{
|
2016-12-28 13:49:37 +00:00
|
|
|
|
if (!gtk_init_check ())
|
1999-02-21 20:55:04 +00:00
|
|
|
|
{
|
2017-11-01 17:26:34 +00:00
|
|
|
|
const char *display_name_arg = NULL;
|
2007-10-15 13:26:34 +00:00
|
|
|
|
if (display_name_arg == NULL)
|
2016-12-28 12:46:56 +00:00
|
|
|
|
display_name_arg = getenv ("DISPLAY");
|
2007-10-15 13:26:34 +00:00
|
|
|
|
g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
|
2001-07-12 17:50:14 +00:00
|
|
|
|
exit (1);
|
1999-02-21 20:55:04 +00:00
|
|
|
|
}
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-01-11 15:13:34 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
|
|
|
|
|
/* This is relevant when building with gcc for Windows (MinGW),
|
|
|
|
|
* where we want to be struct packing compatible with MSVC,
|
|
|
|
|
* i.e. use the -mms-bitfields switch.
|
|
|
|
|
* For Cygwin there should be no need to be compatible with MSVC,
|
|
|
|
|
* so no need to use G_PLATFORM_WIN32.
|
|
|
|
|
*/
|
2000-08-19 21:46:05 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
|
|
|
|
|
{
|
|
|
|
|
if (sizeof_GtkWindow != sizeof (GtkWindow))
|
|
|
|
|
g_error ("Incompatible build!\n"
|
2019-04-05 05:07:32 +00:00
|
|
|
|
"The code using GTK thinks GtkWindow is of different\n"
|
|
|
|
|
"size than it actually is in this build of GTK.\n"
|
2011-01-04 22:32:12 +00:00
|
|
|
|
"On Windows, this probably means that you have compiled\n"
|
|
|
|
|
"your code with gcc without the -mms-bitfields switch,\n"
|
|
|
|
|
"or that you are using an unsupported compiler.");
|
2002-04-18 11:21:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-05 05:07:32 +00:00
|
|
|
|
/* In GTK 2.0 the GtkWindow struct actually is the same size in
|
2002-04-18 11:21:21 +00:00
|
|
|
|
* gcc-compiled code on Win32 whether compiled with -fnative-struct or
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* not. Unfortunately this wan’t noticed until after GTK 2.0.1. So,
|
|
|
|
|
* from GTK 2.0.2 on, check some other struct, too, where the use of
|
2002-04-18 11:21:21 +00:00
|
|
|
|
* -fnative-struct still matters. GtkBox is one such.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
check_sizeof_GtkBox (size_t sizeof_GtkBox)
|
|
|
|
|
{
|
|
|
|
|
if (sizeof_GtkBox != sizeof (GtkBox))
|
|
|
|
|
g_error ("Incompatible build!\n"
|
2019-04-05 05:07:32 +00:00
|
|
|
|
"The code using GTK thinks GtkBox is of different\n"
|
|
|
|
|
"size than it actually is in this build of GTK.\n"
|
2011-01-04 22:32:12 +00:00
|
|
|
|
"On Windows, this probably means that you have compiled\n"
|
|
|
|
|
"your code with gcc without the -mms-bitfields switch,\n"
|
|
|
|
|
"or that you are using an unsupported compiler.");
|
2000-08-19 21:46:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* These two functions might get more checks added later, thus pass
|
|
|
|
|
* in the number of extra args.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2017-01-20 10:38:53 +00:00
|
|
|
|
gtk_init_abi_check (int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
|
2000-08-19 21:46:05 +00:00
|
|
|
|
{
|
|
|
|
|
check_sizeof_GtkWindow (sizeof_GtkWindow);
|
2002-04-18 11:21:21 +00:00
|
|
|
|
if (num_checks >= 2)
|
|
|
|
|
check_sizeof_GtkBox (sizeof_GtkBox);
|
2017-01-20 10:38:53 +00:00
|
|
|
|
gtk_init ();
|
2000-08-19 21:46:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2017-01-20 10:38:53 +00:00
|
|
|
|
gtk_init_check_abi_check (int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
|
2000-08-19 21:46:05 +00:00
|
|
|
|
{
|
|
|
|
|
check_sizeof_GtkWindow (sizeof_GtkWindow);
|
2002-04-18 11:21:21 +00:00
|
|
|
|
if (num_checks >= 2)
|
|
|
|
|
check_sizeof_GtkBox (sizeof_GtkBox);
|
2017-01-20 10:38:53 +00:00
|
|
|
|
return gtk_init_check ();
|
2000-08-19 21:46:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-06-08 17:03:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_is_initialized:
|
|
|
|
|
*
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* Use this function to check if GTK has been initialized with gtk_init()
|
2018-06-08 17:03:22 +00:00
|
|
|
|
* or gtk_init_check().
|
|
|
|
|
*
|
|
|
|
|
* Returns: the initialization status
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
gtk_is_initialized (void)
|
|
|
|
|
{
|
|
|
|
|
return gtk_initialized;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-08 17:10:59 +00:00
|
|
|
|
|
2013-12-10 21:27:24 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_get_locale_direction:
|
|
|
|
|
*
|
|
|
|
|
* Get the direction of the current locale. This is the expected
|
|
|
|
|
* reading direction for text and UI.
|
|
|
|
|
*
|
|
|
|
|
* This function depends on the current locale being set with
|
|
|
|
|
* setlocale() and will default to setting the %GTK_TEXT_DIR_LTR
|
|
|
|
|
* direction otherwise. %GTK_TEXT_DIR_NONE will never be returned.
|
|
|
|
|
*
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* GTK sets the default text direction according to the locale
|
2013-12-10 21:27:24 +00:00
|
|
|
|
* during gtk_init(), and you should normally use
|
|
|
|
|
* gtk_widget_get_direction() or gtk_widget_get_default_direction()
|
2020-05-28 08:00:03 +00:00
|
|
|
|
* to obtain the current direction.
|
2013-12-10 21:27:24 +00:00
|
|
|
|
*
|
|
|
|
|
* This function is only needed rare cases when the locale is
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* changed after GTK has already been initialized. In this case,
|
2013-12-10 21:27:24 +00:00
|
|
|
|
* you can use it to update the default text direction as follows:
|
|
|
|
|
*
|
2014-01-27 19:55:18 +00:00
|
|
|
|
* |[<!-- language="C" -->
|
2013-12-10 21:27:24 +00:00
|
|
|
|
* setlocale (LC_ALL, new_locale);
|
|
|
|
|
* direction = gtk_get_locale_direction ();
|
|
|
|
|
* gtk_widget_set_default_direction (direction);
|
|
|
|
|
* ]|
|
|
|
|
|
*
|
|
|
|
|
* Returns: the #GtkTextDirection of the current locale
|
|
|
|
|
*/
|
|
|
|
|
GtkTextDirection
|
|
|
|
|
gtk_get_locale_direction (void)
|
|
|
|
|
{
|
|
|
|
|
/* Translate to default:RTL if you want your widgets
|
|
|
|
|
* to be RTL, otherwise translate to default:LTR.
|
|
|
|
|
* Do *not* translate it to "predefinito:LTR", if it
|
|
|
|
|
* it isn't default:LTR or default:RTL it will not work
|
|
|
|
|
*/
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *e = _("default:LTR");
|
2013-12-11 01:01:48 +00:00
|
|
|
|
GtkTextDirection dir = GTK_TEXT_DIR_LTR;
|
|
|
|
|
|
2013-12-10 21:27:24 +00:00
|
|
|
|
if (g_strcmp0 (e, "default:RTL") == 0)
|
|
|
|
|
dir = GTK_TEXT_DIR_RTL;
|
|
|
|
|
else if (g_strcmp0 (e, "default:LTR") != 0)
|
2016-02-28 16:06:25 +00:00
|
|
|
|
g_warning ("Whoever translated default:LTR did so wrongly. Defaulting to LTR.");
|
2013-12-10 21:27:24 +00:00
|
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-20 23:52:16 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_get_default_language:
|
|
|
|
|
*
|
|
|
|
|
* Returns the #PangoLanguage for the default language currently in
|
|
|
|
|
* effect. (Note that this can change over the life of an
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* application.) The default language is derived from the current
|
2019-04-05 05:07:32 +00:00
|
|
|
|
* locale. It determines, for example, whether GTK uses the
|
Bug 340141 – Update to Pango 1.16 API
2006-12-24 Behdad Esfahbod <behdad@gnome.org>
Bug 340141 – Update to Pango 1.16 API
* gdk/gdkpango.c (layout_iter_get_line_clip_region),
(gdk_pango_layout_line_get_clip_region):
* gtk/gtkcalendar.c (gtk_calendar_size_request):
* gtk/gtkentry.c (gtk_entry_get_pixel_ranges),
(get_layout_position), (gtk_entry_find_position),
(gtk_entry_adjust_scroll):
* gtk/gtkiconview.c (get_pango_text_offsets):
* gtk/gtklabel.c (get_cursor_direction):
* gtk/gtkstyle.c (get_insensitive_layout):
* gtk/gtktextdisplay.c (render_para):
* gtk/gtktextlayout.c (allocate_child_widgets),
(find_display_line_below), (find_display_line_above),
(gtk_text_layout_move_iter_to_previous_line),
(gtk_text_layout_move_iter_to_next_line),
(gtk_text_layout_move_iter_to_line_end),
(gtk_text_layout_iter_starts_line),
(gtk_text_layout_move_iter_to_x):
* gtk/gtktextutil.c (limit_layout_lines):
Use the _readonly version of pango_layout_iter_get_line(),
pango_layout_iter_get_run(), pango_layout_get_line(), and
pango_layout_get_lines().
* gtk/gtkmain.c (gtk_get_default_language): Use
pango_get_default_language().
2006-12-24 05:29:25 +00:00
|
|
|
|
* right-to-left or left-to-right text direction.
|
|
|
|
|
*
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* This function is equivalent to pango_language_get_default().
|
|
|
|
|
* See that function for details.
|
|
|
|
|
*
|
2014-08-21 21:10:32 +00:00
|
|
|
|
* Returns: (transfer none): the default language as a #PangoLanguage,
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* must not be freed
|
|
|
|
|
*/
|
2003-09-20 23:52:16 +00:00
|
|
|
|
PangoLanguage *
|
|
|
|
|
gtk_get_default_language (void)
|
|
|
|
|
{
|
Bug 340141 – Update to Pango 1.16 API
2006-12-24 Behdad Esfahbod <behdad@gnome.org>
Bug 340141 – Update to Pango 1.16 API
* gdk/gdkpango.c (layout_iter_get_line_clip_region),
(gdk_pango_layout_line_get_clip_region):
* gtk/gtkcalendar.c (gtk_calendar_size_request):
* gtk/gtkentry.c (gtk_entry_get_pixel_ranges),
(get_layout_position), (gtk_entry_find_position),
(gtk_entry_adjust_scroll):
* gtk/gtkiconview.c (get_pango_text_offsets):
* gtk/gtklabel.c (get_cursor_direction):
* gtk/gtkstyle.c (get_insensitive_layout):
* gtk/gtktextdisplay.c (render_para):
* gtk/gtktextlayout.c (allocate_child_widgets),
(find_display_line_below), (find_display_line_above),
(gtk_text_layout_move_iter_to_previous_line),
(gtk_text_layout_move_iter_to_next_line),
(gtk_text_layout_move_iter_to_line_end),
(gtk_text_layout_iter_starts_line),
(gtk_text_layout_move_iter_to_x):
* gtk/gtktextutil.c (limit_layout_lines):
Use the _readonly version of pango_layout_iter_get_line(),
pango_layout_iter_get_run(), pango_layout_get_line(), and
pango_layout_get_lines().
* gtk/gtkmain.c (gtk_get_default_language): Use
pango_get_default_language().
2006-12-24 05:29:25 +00:00
|
|
|
|
return pango_language_get_default ();
|
2000-06-21 20:41:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-30 00:05:02 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
GMainLoop *store_loop;
|
|
|
|
|
guint n_clipboards;
|
2020-01-10 23:04:44 +00:00
|
|
|
|
guint timeout_id;
|
2017-11-30 00:05:02 +00:00
|
|
|
|
} ClipboardStore;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
clipboard_store_finished (GObject *source,
|
|
|
|
|
GAsyncResult *result,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
ClipboardStore *store;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
if (!gdk_clipboard_store_finish (GDK_CLIPBOARD (source), result, &error))
|
|
|
|
|
{
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
{
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
store = data;
|
|
|
|
|
store->n_clipboards--;
|
|
|
|
|
if (store->n_clipboards == 0)
|
|
|
|
|
g_main_loop_quit (store->store_loop);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-10 23:04:44 +00:00
|
|
|
|
static gboolean
|
|
|
|
|
sync_timed_out_cb (ClipboardStore *store)
|
|
|
|
|
{
|
|
|
|
|
store->timeout_id = 0;
|
|
|
|
|
g_main_loop_quit (store->store_loop);
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-29 23:09:37 +00:00
|
|
|
|
void
|
|
|
|
|
gtk_main_sync (void)
|
|
|
|
|
{
|
2017-11-30 00:05:02 +00:00
|
|
|
|
ClipboardStore store = { NULL, };
|
|
|
|
|
GSList *displays, *l;
|
|
|
|
|
GCancellable *cancel;
|
|
|
|
|
|
|
|
|
|
/* Try storing all clipboard data we have */
|
|
|
|
|
displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
|
2020-01-10 23:00:10 +00:00
|
|
|
|
if (displays == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-30 00:05:02 +00:00
|
|
|
|
cancel = g_cancellable_new ();
|
|
|
|
|
|
|
|
|
|
for (l = displays; l; l = l->next)
|
|
|
|
|
{
|
|
|
|
|
GdkDisplay *display = l->data;
|
|
|
|
|
GdkClipboard *clipboard = gdk_display_get_clipboard (display);
|
|
|
|
|
|
|
|
|
|
gdk_clipboard_store_async (clipboard,
|
|
|
|
|
G_PRIORITY_HIGH,
|
|
|
|
|
cancel,
|
|
|
|
|
clipboard_store_finished,
|
|
|
|
|
&store);
|
|
|
|
|
store.n_clipboards++;
|
|
|
|
|
}
|
|
|
|
|
g_slist_free (displays);
|
|
|
|
|
|
|
|
|
|
store.store_loop = g_main_loop_new (NULL, TRUE);
|
2020-01-10 23:04:44 +00:00
|
|
|
|
store.timeout_id = g_timeout_add_seconds (10, (GSourceFunc) sync_timed_out_cb, &store);
|
|
|
|
|
g_source_set_name_by_id (store.timeout_id, "[gtk] gtk_main_sync clipboard store timeout");
|
2017-11-30 00:05:02 +00:00
|
|
|
|
|
|
|
|
|
if (g_main_loop_is_running (store.store_loop))
|
2018-02-02 15:34:40 +00:00
|
|
|
|
g_main_loop_run (store.store_loop);
|
2017-11-30 00:05:02 +00:00
|
|
|
|
|
|
|
|
|
g_cancellable_cancel (cancel);
|
|
|
|
|
g_object_unref (cancel);
|
2020-01-10 23:04:44 +00:00
|
|
|
|
g_clear_handle_id (&store.timeout_id, g_source_remove);
|
|
|
|
|
g_clear_pointer (&store.store_loop, g_main_loop_unref);
|
2017-11-30 00:05:02 +00:00
|
|
|
|
|
2017-11-29 23:09:37 +00:00
|
|
|
|
/* Synchronize the recent manager singleton */
|
|
|
|
|
_gtk_recent_manager_sync ();
|
1997-11-28 01:22:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-03 15:04:56 +00:00
|
|
|
|
static GdkEvent *
|
2018-03-20 14:14:10 +00:00
|
|
|
|
rewrite_event_for_surface (GdkEvent *event,
|
2018-03-21 10:49:14 +00:00
|
|
|
|
GdkSurface *new_surface)
|
2002-03-02 20:37:07 +00:00
|
|
|
|
{
|
2020-02-18 03:11:56 +00:00
|
|
|
|
GdkEventType type;
|
2020-02-15 19:06:43 +00:00
|
|
|
|
double x, y;
|
2020-02-18 03:11:56 +00:00
|
|
|
|
double dx, dy;
|
2020-02-15 19:06:43 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
type = gdk_event_get_event_type (event);
|
|
|
|
|
|
|
|
|
|
switch ((guint) type)
|
2020-02-15 19:06:43 +00:00
|
|
|
|
{
|
2020-02-18 03:11:56 +00:00
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
|
case GDK_TOUCH_BEGIN:
|
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
|
|
|
|
case GDK_TOUCHPAD_SWIPE:
|
|
|
|
|
case GDK_TOUCHPAD_PINCH:
|
|
|
|
|
gdk_event_get_position (event, &x, &y);
|
|
|
|
|
gdk_surface_translate_coordinates (gdk_event_get_surface (event), new_surface, &x, &y);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2020-02-15 19:06:43 +00:00
|
|
|
|
x = y = 0;
|
2020-02-18 03:11:56 +00:00
|
|
|
|
break;
|
2020-02-15 19:06:43 +00:00
|
|
|
|
}
|
2002-03-02 20:37:07 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
switch ((guint) type)
|
2002-03-02 20:37:07 +00:00
|
|
|
|
{
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
return gdk_button_event_new (type,
|
2020-02-15 19:06:43 +00:00
|
|
|
|
new_surface,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_device (event),
|
|
|
|
|
gdk_event_get_device_tool (event),
|
|
|
|
|
gdk_event_get_time (event),
|
|
|
|
|
gdk_event_get_modifier_state (event),
|
|
|
|
|
gdk_button_event_get_button (event),
|
2020-02-15 19:06:43 +00:00
|
|
|
|
x, y,
|
2020-12-17 15:32:31 +00:00
|
|
|
|
gdk_event_dup_axes (event));
|
2002-03-02 20:37:07 +00:00
|
|
|
|
case GDK_MOTION_NOTIFY:
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
return gdk_motion_event_new (new_surface,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_device (event),
|
|
|
|
|
gdk_event_get_device_tool (event),
|
|
|
|
|
gdk_event_get_time (event),
|
|
|
|
|
gdk_event_get_modifier_state (event),
|
2020-02-15 19:06:43 +00:00
|
|
|
|
x, y,
|
2020-12-17 15:32:31 +00:00
|
|
|
|
gdk_event_dup_axes (event));
|
2011-12-28 23:06:45 +00:00
|
|
|
|
case GDK_TOUCH_BEGIN:
|
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
return gdk_touch_event_new (type,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_event_sequence (event),
|
2020-02-15 19:06:43 +00:00
|
|
|
|
new_surface,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_device (event),
|
|
|
|
|
gdk_event_get_time (event),
|
|
|
|
|
gdk_event_get_modifier_state (event),
|
2020-02-15 19:06:43 +00:00
|
|
|
|
x, y,
|
2020-12-17 15:32:31 +00:00
|
|
|
|
gdk_event_dup_axes (event),
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_touch_event_get_emulating_pointer (event));
|
2015-07-09 16:47:02 +00:00
|
|
|
|
case GDK_TOUCHPAD_SWIPE:
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_touchpad_event_get_deltas (event, &dx, &dy);
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
return gdk_touchpad_event_new_swipe (new_surface,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_device (event),
|
|
|
|
|
gdk_event_get_time (event),
|
|
|
|
|
gdk_event_get_modifier_state (event),
|
|
|
|
|
gdk_touchpad_event_get_gesture_phase (event),
|
2020-02-15 19:06:43 +00:00
|
|
|
|
x, y,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_touchpad_event_get_n_fingers (event),
|
|
|
|
|
dx, dy);
|
2015-07-09 16:47:02 +00:00
|
|
|
|
case GDK_TOUCHPAD_PINCH:
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_touchpad_event_get_deltas (event, &dx, &dy);
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
return gdk_touchpad_event_new_pinch (new_surface,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_device (event),
|
|
|
|
|
gdk_event_get_time (event),
|
|
|
|
|
gdk_event_get_modifier_state (event),
|
|
|
|
|
gdk_touchpad_event_get_gesture_phase (event),
|
2020-02-15 19:06:43 +00:00
|
|
|
|
x, y,
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_touchpad_event_get_n_fingers (event),
|
|
|
|
|
dx, dy,
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
gdk_touchpad_event_get_pinch_scale (event),
|
|
|
|
|
gdk_touchpad_event_get_pinch_angle_delta (event));
|
2002-03-02 20:37:07 +00:00
|
|
|
|
default:
|
2020-02-15 19:06:43 +00:00
|
|
|
|
break;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-15 19:06:43 +00:00
|
|
|
|
return NULL;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
|
|
|
|
|
* then what X11 does is deliver the event normally if it was going to this
|
2018-03-20 14:14:10 +00:00
|
|
|
|
* client, otherwise, delivers it in terms of the grab surface. This function
|
2002-03-02 20:37:07 +00:00
|
|
|
|
* rewrites events to the effect that events going to the same window group
|
|
|
|
|
* are delivered normally, otherwise, the event is delivered in terms of the
|
|
|
|
|
* grab window.
|
|
|
|
|
*/
|
|
|
|
|
static GdkEvent *
|
|
|
|
|
rewrite_event_for_grabs (GdkEvent *event)
|
|
|
|
|
{
|
2018-03-20 14:14:10 +00:00
|
|
|
|
GdkSurface *grab_surface;
|
2002-03-02 21:01:20 +00:00
|
|
|
|
GtkWidget *event_widget, *grab_widget;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
gboolean owner_events;
|
Integrate Erwann Chenede's multihead changes for the gtk/ directory.
Mon Apr 29 18:28:00 2002 Owen Taylor <otaylor@redhat.com>
Integrate Erwann Chenede's multihead changes for the gtk/ directory.
* gtk/gtkclipboard.[ch]: Add gtk_clipboard_get_for_display(),
make internals multihead aware.
* gtk/gtkcolorsel.[ch]: Add
gtk_color_selection_set_change_palette_with_screen_hook () [ugh!]
make up for non-multihead safety of
gtk_color_selection_set_change_palette_hook()
* gtk/gtkinvisible.[ch] gtk/gtkmenu.[ch] gtkwindow.[ch]: Add
gtk_{invisible,menu,window}_set_screen(); add "screen" properties
for GtkWindow and GtkMenu.
* gtk/gtkplug.[ch]: Add gtk_plug_construct_for_display(),
gtk_plug_new_for_display(). Multihead fixes.
* gtk/gtkselection.[ch]: Add gtk_selection_owner_set_for_display(),
make internals multihead aware.
* gtk/gtksettings.[ch]: Add gtk_settings_get_for_screen(), get
rid of now-useless gtk_settings_constructor().
* gtk/gtkstyle.[ch]: Add gtk_style_get_font_for_display(), fix
check/radio button indicators bitmap handling to be multihead
safe.
* gtk/gtkwidget.[ch]: Add gtk_widget_get_screen(), gtk_widget_has_screen(),
gtk_widget_get_display(), gtk_widget_get_clipboard(),
gtk_widget_get_root_window().
* gtk/gtkbindings.c gtk/gtkbutton.c gtk/gtkclist.c gtk/gtkcombo.c
gtk/gtkctree.c gtk/gtkdnd.c gtk/gtkfilesel.c gtk/gtkgamma.c
gtk/gtkhandlebox.c gtk/gtkhsv.c gtk/gtkimcontext.c gtk/gtklabel.c
gtk/gtklist.c gtk/gtkmain.c gtk/gtkmenuitem.c gtk/gtkmenushell.c
gtk/gtknotebook.c gtk/gtkoldeditable.c gtk/gtkoptionmenu.c
gtk/gtkpaned.c gtk/gtkpreview.c gtk/gtksocket.c gtk/gtktext.c
gtk/gtktextbuffer.c gtk/gtktextview.c gtk/gtktipsquery.c
gtk/gtktooltips.c gtk/gtktreeview.c gtk/gtktreeviewcolumn.c:
misc mechanical multihead-safety fixes.
* gtk/gtkclipboard.c: Use a GtkImage rather than a pixmap for
the dropper, look up the color palette only at realization time,
other multihead fixes.
* gtk/gtkcombo.c (gtk_combo_unrealize): Popdown the list when
unrealizing.
* gtk/gtkentry.c: Only claim ownership of the primary selection
when realized, misc multihead fixes.
* gtk/gtkfontsel.c: Only fill in fonts when attached to a screen,
fix gtk_font_selection_get_font() for multihead.
* gtk/gtkgc.c: make the depth => drawable hash per-screen.
* gtk/gtkinvisible.c: Add a constructor that realizes the
widget, so we get a realized widget with g_object_new() as
well gtk_invisible_new() as before.
* gtk/gtkmain.c: Get rid of unused gtk_visual/gtk_colormap
variables.
* gtk/gtktextdisplay.c: Add warnings if stipple bitmaps
are used on the wrong screen.
* gtk/gtktoolbar.c: Make handling of GtkSettings-based layout
read properties and connect to settings when the screen is changed,
rather than on init/finalize.
* gtk/gtkwindow.c: Fix icon handing to be multihead safe ...
default icon pixmaps/mask are only shared between windows on the
same screen. Misc multihead fixes.
Sat Apr 27 13:49:53 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkclipboard.c (gtk_clipboard_get_for_display):
Update docs to reference GDK_SELECTION_CLIPBOARD rather GDK_NONE.
2002-04-29 Alex Larsson <alexl@redhat.com>
* gdk/linux-fb/gdkproperty-fb.c (gdk_property_get):
Fix silly bug, noticed by Sven Neumann.
Sun Apr 28 22:43:55 2002 Jonathan Blandford <jrb@gnome.org>
* gtk/gtktreemodelsort.c (gtk_tree_model_sort_set_sort_func): Fix
so that you can set a new sort func.
2002-04-29 22:53:45 +00:00
|
|
|
|
GdkDisplay *display;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
GdkDevice *device;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
switch ((guint) gdk_event_get_event_type (event))
|
2002-03-02 20:37:07 +00:00
|
|
|
|
{
|
|
|
|
|
case GDK_SCROLL:
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
|
case GDK_PROXIMITY_IN:
|
|
|
|
|
case GDK_PROXIMITY_OUT:
|
|
|
|
|
case GDK_KEY_PRESS:
|
|
|
|
|
case GDK_KEY_RELEASE:
|
2011-12-28 23:06:45 +00:00
|
|
|
|
case GDK_TOUCH_BEGIN:
|
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
2015-07-09 16:47:02 +00:00
|
|
|
|
case GDK_TOUCHPAD_SWIPE:
|
|
|
|
|
case GDK_TOUCHPAD_PINCH:
|
2020-02-18 03:11:56 +00:00
|
|
|
|
display = gdk_event_get_display (event);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
device = gdk_event_get_device (event);
|
|
|
|
|
|
2018-03-20 14:14:10 +00:00
|
|
|
|
if (!gdk_device_grab_info (display, device, &grab_surface, &owner_events) ||
|
2011-01-04 22:32:12 +00:00
|
|
|
|
!owner_events)
|
2010-05-25 22:38:44 +00:00
|
|
|
|
return NULL;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
event_widget = gtk_get_event_widget (event);
|
2020-08-13 23:21:05 +00:00
|
|
|
|
grab_widget = GTK_WIDGET (gtk_native_get_for_surface (grab_surface));
|
2002-03-02 20:37:07 +00:00
|
|
|
|
|
|
|
|
|
if (grab_widget &&
|
|
|
|
|
gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
|
2018-03-20 14:14:10 +00:00
|
|
|
|
return rewrite_event_for_surface (event, grab_surface);
|
2002-03-02 20:37:07 +00:00
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-15 18:56:32 +00:00
|
|
|
|
static GdkEvent *
|
|
|
|
|
rewrite_event_for_toplevel (GdkEvent *event)
|
|
|
|
|
{
|
|
|
|
|
GdkSurface *surface;
|
2020-05-12 08:36:18 +00:00
|
|
|
|
GdkEventType event_type;
|
2020-05-22 11:37:37 +00:00
|
|
|
|
GdkTranslatedKey *key, *key_no_lock;
|
2020-04-15 18:56:32 +00:00
|
|
|
|
|
|
|
|
|
surface = gdk_event_get_surface (event);
|
|
|
|
|
if (!surface->parent)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2020-05-12 08:36:18 +00:00
|
|
|
|
event_type = gdk_event_get_event_type (event);
|
|
|
|
|
if (event_type != GDK_KEY_PRESS &&
|
|
|
|
|
event_type != GDK_KEY_RELEASE)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2020-04-15 18:56:32 +00:00
|
|
|
|
while (surface->parent)
|
|
|
|
|
surface = surface->parent;
|
|
|
|
|
|
2020-05-22 11:37:37 +00:00
|
|
|
|
key = gdk_key_event_get_translated_key (event, FALSE);
|
|
|
|
|
key_no_lock = gdk_key_event_get_translated_key (event, TRUE);
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
|
|
|
|
|
return gdk_key_event_new (gdk_event_get_event_type (event),
|
2020-04-15 18:56:32 +00:00
|
|
|
|
surface,
|
|
|
|
|
gdk_event_get_device (event),
|
|
|
|
|
gdk_event_get_time (event),
|
|
|
|
|
gdk_key_event_get_keycode (event),
|
|
|
|
|
gdk_event_get_modifier_state (event),
|
|
|
|
|
gdk_key_event_is_modifier (event),
|
2020-05-22 11:37:37 +00:00
|
|
|
|
key, key_no_lock);
|
2020-04-15 18:56:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-22 20:33:53 +00:00
|
|
|
|
static gboolean
|
2020-02-16 01:47:23 +00:00
|
|
|
|
translate_event_coordinates (GdkEvent *event,
|
|
|
|
|
double *x,
|
|
|
|
|
double *y,
|
|
|
|
|
GtkWidget *widget)
|
2017-03-31 15:38:38 +00:00
|
|
|
|
{
|
2020-02-16 01:47:23 +00:00
|
|
|
|
GtkWidget *event_widget;
|
2020-05-17 06:22:29 +00:00
|
|
|
|
GtkNative *native;
|
2020-02-16 01:47:23 +00:00
|
|
|
|
graphene_point_t p;
|
|
|
|
|
double event_x, event_y;
|
2020-05-17 21:08:01 +00:00
|
|
|
|
double native_x, native_y;
|
2019-03-07 03:25:31 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
*x = *y = 0;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
if (!gdk_event_get_position (event, &event_x, &event_y))
|
2020-02-16 01:47:23 +00:00
|
|
|
|
return FALSE;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
event_widget = gtk_get_event_widget (event);
|
2020-05-17 06:22:29 +00:00
|
|
|
|
native = gtk_widget_get_native (event_widget);
|
|
|
|
|
|
|
|
|
|
gtk_native_get_surface_transform (GTK_NATIVE (native), &native_x, &native_y);
|
|
|
|
|
event_x -= native_x;
|
|
|
|
|
event_y -= native_y;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
if (!gtk_widget_compute_point (event_widget,
|
|
|
|
|
widget,
|
|
|
|
|
&GRAPHENE_POINT_INIT (event_x, event_y),
|
|
|
|
|
&p))
|
|
|
|
|
return FALSE;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
*x = p.x;
|
|
|
|
|
*y = p.y;
|
2019-03-08 18:52:46 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
return TRUE;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 03:44:41 +00:00
|
|
|
|
static void
|
2019-03-16 07:06:29 +00:00
|
|
|
|
gtk_synthesize_crossing_events (GtkRoot *toplevel,
|
2020-02-19 03:44:41 +00:00
|
|
|
|
GtkCrossingType crossing_type,
|
2017-05-24 23:50:38 +00:00
|
|
|
|
GtkWidget *old_target,
|
|
|
|
|
GtkWidget *new_target,
|
|
|
|
|
GdkEvent *event,
|
2020-02-19 03:44:41 +00:00
|
|
|
|
GdkCrossingMode mode,
|
|
|
|
|
GdkDrop *drop)
|
2017-05-24 23:50:38 +00:00
|
|
|
|
{
|
2020-02-16 01:47:23 +00:00
|
|
|
|
GtkCrossingData crossing;
|
2020-02-21 04:20:58 +00:00
|
|
|
|
GtkWidget *ancestor;
|
2020-02-16 01:47:23 +00:00
|
|
|
|
GtkWidget *widget;
|
|
|
|
|
double x, y;
|
2020-02-21 04:20:58 +00:00
|
|
|
|
GtkWidget *prev;
|
|
|
|
|
gboolean seen_ancestor;
|
2020-07-02 18:50:14 +00:00
|
|
|
|
GtkWidgetStack target_array;
|
2020-04-10 06:17:46 +00:00
|
|
|
|
int i;
|
2020-02-21 04:20:58 +00:00
|
|
|
|
|
2020-02-22 03:27:06 +00:00
|
|
|
|
if (old_target == new_target)
|
|
|
|
|
return;
|
|
|
|
|
|
2020-02-21 04:20:58 +00:00
|
|
|
|
if (old_target && new_target)
|
|
|
|
|
ancestor = gtk_widget_common_ancestor (old_target, new_target);
|
|
|
|
|
else
|
|
|
|
|
ancestor = NULL;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-19 03:44:41 +00:00
|
|
|
|
crossing.type = crossing_type;
|
2020-02-16 01:47:23 +00:00
|
|
|
|
crossing.mode = mode;
|
2020-08-26 11:26:01 +00:00
|
|
|
|
crossing.old_target = old_target ? g_object_ref (old_target) : NULL;
|
2020-02-21 04:20:58 +00:00
|
|
|
|
crossing.old_descendent = NULL;
|
2020-08-26 11:26:01 +00:00
|
|
|
|
crossing.new_target = new_target ? g_object_ref (new_target) : NULL;
|
2020-02-21 04:20:58 +00:00
|
|
|
|
crossing.new_descendent = NULL;
|
2020-02-19 03:44:41 +00:00
|
|
|
|
crossing.drop = drop;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
crossing.direction = GTK_CROSSING_OUT;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-21 04:20:58 +00:00
|
|
|
|
prev = NULL;
|
|
|
|
|
seen_ancestor = FALSE;
|
2020-02-16 01:47:23 +00:00
|
|
|
|
widget = old_target;
|
|
|
|
|
while (widget)
|
2017-03-31 15:38:38 +00:00
|
|
|
|
{
|
2020-02-21 04:20:58 +00:00
|
|
|
|
crossing.old_descendent = prev;
|
|
|
|
|
if (seen_ancestor)
|
|
|
|
|
{
|
|
|
|
|
crossing.new_descendent = new_target ? prev : NULL;
|
|
|
|
|
}
|
|
|
|
|
else if (widget == ancestor)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *w;
|
|
|
|
|
|
|
|
|
|
crossing.new_descendent = NULL;
|
2020-04-29 06:15:23 +00:00
|
|
|
|
for (w = new_target; w != ancestor; w = _gtk_widget_get_parent (w))
|
2020-02-21 04:20:58 +00:00
|
|
|
|
crossing.new_descendent = w;
|
|
|
|
|
|
|
|
|
|
seen_ancestor = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
crossing.new_descendent = NULL;
|
|
|
|
|
}
|
|
|
|
|
check_crossing_invariants (widget, &crossing);
|
2020-02-16 01:47:23 +00:00
|
|
|
|
translate_event_coordinates (event, &x, &y, widget);
|
|
|
|
|
gtk_widget_handle_crossing (widget, &crossing, x, y);
|
2020-02-19 03:44:41 +00:00
|
|
|
|
if (crossing_type == GTK_CROSSING_POINTER)
|
|
|
|
|
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
|
2020-04-02 04:39:46 +00:00
|
|
|
|
prev = widget;
|
2020-04-29 06:15:23 +00:00
|
|
|
|
widget = _gtk_widget_get_parent (widget);
|
2017-03-31 15:38:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
gtk_widget_stack_init (&target_array);
|
2020-04-29 06:15:23 +00:00
|
|
|
|
for (widget = new_target; widget; widget = _gtk_widget_get_parent (widget))
|
2020-07-02 18:50:14 +00:00
|
|
|
|
gtk_widget_stack_append (&target_array, g_object_ref (widget));
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
crossing.direction = GTK_CROSSING_IN;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2020-02-21 04:20:58 +00:00
|
|
|
|
seen_ancestor = FALSE;
|
2020-07-02 18:50:14 +00:00
|
|
|
|
for (i = gtk_widget_stack_get_size (&target_array) - 1; i >= 0; i--)
|
2020-02-16 01:47:23 +00:00
|
|
|
|
{
|
2020-07-02 18:50:14 +00:00
|
|
|
|
widget = gtk_widget_stack_get (&target_array, i);
|
2020-04-10 06:17:46 +00:00
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
if (i < gtk_widget_stack_get_size (&target_array) - 1)
|
|
|
|
|
crossing.new_descendent = gtk_widget_stack_get (&target_array, i + 1);
|
2020-02-21 04:20:58 +00:00
|
|
|
|
else
|
|
|
|
|
crossing.new_descendent = NULL;
|
2020-04-10 06:17:46 +00:00
|
|
|
|
|
2020-02-21 04:20:58 +00:00
|
|
|
|
if (seen_ancestor)
|
|
|
|
|
{
|
|
|
|
|
crossing.old_descendent = NULL;
|
|
|
|
|
}
|
|
|
|
|
else if (widget == ancestor)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *w;
|
|
|
|
|
|
|
|
|
|
crossing.old_descendent = NULL;
|
2020-04-29 06:15:23 +00:00
|
|
|
|
for (w = old_target; w != ancestor; w = _gtk_widget_get_parent (w))
|
2020-02-21 04:20:58 +00:00
|
|
|
|
crossing.old_descendent = w;
|
|
|
|
|
|
|
|
|
|
seen_ancestor = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
crossing.old_descendent = old_target ? crossing.new_descendent : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
translate_event_coordinates (event, &x, &y, widget);
|
|
|
|
|
gtk_widget_handle_crossing (widget, &crossing, x, y);
|
2020-02-19 03:44:41 +00:00
|
|
|
|
if (crossing_type == GTK_CROSSING_POINTER)
|
|
|
|
|
gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
|
2017-03-31 15:38:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-26 11:26:01 +00:00
|
|
|
|
g_clear_object (&crossing.old_target);
|
|
|
|
|
g_clear_object (&crossing.new_target);
|
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
gtk_widget_stack_clear (&target_array);
|
2020-02-16 01:47:23 +00:00
|
|
|
|
}
|
2019-03-07 03:25:31 +00:00
|
|
|
|
|
|
|
|
|
static GtkWidget *
|
|
|
|
|
update_pointer_focus_state (GtkWindow *toplevel,
|
|
|
|
|
GdkEvent *event,
|
|
|
|
|
GtkWidget *new_target)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *old_target = NULL;
|
|
|
|
|
GdkEventSequence *sequence;
|
|
|
|
|
GdkDevice *device;
|
2020-05-17 21:08:01 +00:00
|
|
|
|
double x, y;
|
|
|
|
|
double nx, ny;
|
2019-03-07 03:25:31 +00:00
|
|
|
|
|
|
|
|
|
device = gdk_event_get_device (event);
|
|
|
|
|
sequence = gdk_event_get_event_sequence (event);
|
|
|
|
|
old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence);
|
|
|
|
|
if (old_target == new_target)
|
|
|
|
|
return old_target;
|
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_position (event, &x, &y);
|
2020-05-17 06:22:29 +00:00
|
|
|
|
gtk_native_get_surface_transform (GTK_NATIVE (toplevel), &nx, &ny);
|
|
|
|
|
x -= nx;
|
|
|
|
|
y -= ny;
|
|
|
|
|
|
2019-03-07 03:25:31 +00:00
|
|
|
|
gtk_window_update_pointer_focus (toplevel, device, sequence,
|
|
|
|
|
new_target, x, y);
|
|
|
|
|
|
|
|
|
|
return old_target;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-31 15:38:38 +00:00
|
|
|
|
static gboolean
|
|
|
|
|
is_pointing_event (GdkEvent *event)
|
|
|
|
|
{
|
2020-02-18 03:11:56 +00:00
|
|
|
|
switch ((guint) gdk_event_get_event_type (event))
|
2017-03-31 15:38:38 +00:00
|
|
|
|
{
|
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
|
case GDK_ENTER_NOTIFY:
|
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
|
case GDK_SCROLL:
|
|
|
|
|
case GDK_TOUCH_BEGIN:
|
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
|
|
|
|
case GDK_TOUCHPAD_PINCH:
|
|
|
|
|
case GDK_TOUCHPAD_SWIPE:
|
2020-02-19 03:44:41 +00:00
|
|
|
|
case GDK_DRAG_ENTER:
|
|
|
|
|
case GDK_DRAG_LEAVE:
|
|
|
|
|
case GDK_DRAG_MOTION:
|
|
|
|
|
case GDK_DROP_START:
|
2017-03-31 15:38:38 +00:00
|
|
|
|
return TRUE;
|
2020-02-19 03:44:41 +00:00
|
|
|
|
|
2020-05-12 08:36:18 +00:00
|
|
|
|
case GDK_GRAB_BROKEN:
|
|
|
|
|
return gdk_device_get_source (gdk_event_get_device (event)) != GDK_SOURCE_KEYBOARD;
|
|
|
|
|
|
2017-03-31 15:38:38 +00:00
|
|
|
|
default:
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-17 23:41:26 +00:00
|
|
|
|
static gboolean
|
|
|
|
|
is_key_event (GdkEvent *event)
|
|
|
|
|
{
|
2020-02-18 03:11:56 +00:00
|
|
|
|
switch ((guint) gdk_event_get_event_type (event))
|
2019-03-17 23:41:26 +00:00
|
|
|
|
{
|
|
|
|
|
case GDK_KEY_PRESS:
|
|
|
|
|
case GDK_KEY_RELEASE:
|
|
|
|
|
return TRUE;
|
|
|
|
|
break;
|
2020-05-12 08:36:18 +00:00
|
|
|
|
case GDK_GRAB_BROKEN:
|
|
|
|
|
return gdk_device_get_source (gdk_event_get_device (event)) == GDK_SOURCE_KEYBOARD;
|
2019-03-17 23:41:26 +00:00
|
|
|
|
default:
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-25 04:39:04 +00:00
|
|
|
|
static inline void
|
|
|
|
|
set_widget_active_state (GtkWidget *target,
|
|
|
|
|
const gboolean release)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *w;
|
|
|
|
|
|
|
|
|
|
w = target;
|
|
|
|
|
while (w)
|
|
|
|
|
{
|
|
|
|
|
if (release)
|
2020-11-12 23:23:52 +00:00
|
|
|
|
gtk_widget_set_active_state (w, FALSE);
|
2019-01-25 04:39:04 +00:00
|
|
|
|
else
|
2020-11-12 23:23:52 +00:00
|
|
|
|
gtk_widget_set_active_state (w, TRUE);
|
2019-01-25 04:39:04 +00:00
|
|
|
|
|
2020-04-29 06:15:23 +00:00
|
|
|
|
w = _gtk_widget_get_parent (w);
|
2019-01-25 04:39:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-31 15:38:38 +00:00
|
|
|
|
static GtkWidget *
|
|
|
|
|
handle_pointing_event (GdkEvent *event)
|
|
|
|
|
{
|
2019-02-03 04:37:13 +00:00
|
|
|
|
GtkWidget *target = NULL, *old_target = NULL, *event_widget;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
GtkWindow *toplevel;
|
|
|
|
|
GdkEventSequence *sequence;
|
|
|
|
|
GdkDevice *device;
|
2020-05-15 06:22:04 +00:00
|
|
|
|
double x, y;
|
2020-05-17 21:08:01 +00:00
|
|
|
|
double native_x, native_y;
|
2019-03-17 23:41:26 +00:00
|
|
|
|
GtkWidget *native;
|
2020-02-18 03:11:56 +00:00
|
|
|
|
GdkEventType type;
|
2020-11-19 19:12:58 +00:00
|
|
|
|
gboolean has_implicit;
|
2020-12-08 22:13:50 +00:00
|
|
|
|
GdkModifierType modifiers;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2019-02-03 04:37:13 +00:00
|
|
|
|
event_widget = gtk_get_event_widget (event);
|
2017-03-31 15:38:38 +00:00
|
|
|
|
device = gdk_event_get_device (event);
|
2020-02-18 03:11:56 +00:00
|
|
|
|
gdk_event_get_position (event, &x, &y);
|
2017-03-31 15:38:38 +00:00
|
|
|
|
|
2019-03-17 23:41:26 +00:00
|
|
|
|
toplevel = GTK_WINDOW (gtk_widget_get_root (event_widget));
|
2019-05-02 21:33:53 +00:00
|
|
|
|
native = GTK_WIDGET (gtk_widget_get_native (event_widget));
|
2017-06-26 10:00:20 +00:00
|
|
|
|
|
2020-05-15 06:22:04 +00:00
|
|
|
|
gtk_native_get_surface_transform (GTK_NATIVE (native), &native_x, &native_y);
|
|
|
|
|
x -= native_x;
|
|
|
|
|
y -= native_y;
|
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
type = gdk_event_get_event_type (event);
|
2017-03-31 15:38:38 +00:00
|
|
|
|
sequence = gdk_event_get_event_sequence (event);
|
|
|
|
|
|
2020-07-28 22:03:48 +00:00
|
|
|
|
if (type == GDK_SCROLL &&
|
|
|
|
|
(gdk_device_get_source (device) == GDK_SOURCE_TOUCHPAD ||
|
|
|
|
|
gdk_device_get_source (device) == GDK_SOURCE_TRACKPOINT ||
|
|
|
|
|
gdk_device_get_source (device) == GDK_SOURCE_MOUSE))
|
|
|
|
|
{
|
|
|
|
|
/* A bit of a kludge, resolve target lookups for scrolling devices
|
|
|
|
|
* on the seat pointer.
|
|
|
|
|
*/
|
|
|
|
|
device = gdk_seat_get_pointer (gdk_event_get_seat (event));
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
switch ((guint) type)
|
2017-03-31 15:38:38 +00:00
|
|
|
|
{
|
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
|
|
|
|
old_target = update_pointer_focus_state (toplevel, event, NULL);
|
2020-11-12 16:31:52 +00:00
|
|
|
|
if (type == GDK_TOUCH_END || type == GDK_TOUCH_CANCEL)
|
|
|
|
|
set_widget_active_state (old_target, TRUE);
|
|
|
|
|
else if (type == GDK_LEAVE_NOTIFY)
|
2020-02-19 03:44:41 +00:00
|
|
|
|
gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, old_target, NULL,
|
|
|
|
|
event, gdk_crossing_event_get_mode (event), NULL);
|
|
|
|
|
break;
|
|
|
|
|
case GDK_DRAG_LEAVE:
|
2020-02-29 02:47:17 +00:00
|
|
|
|
{
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
GdkDrop *drop = gdk_dnd_event_get_drop (event);
|
2020-02-29 02:47:17 +00:00
|
|
|
|
old_target = update_pointer_focus_state (toplevel, event, NULL);
|
|
|
|
|
gtk_drop_begin_event (drop, GDK_DRAG_LEAVE);
|
|
|
|
|
gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_DROP, old_target, NULL,
|
|
|
|
|
event, GDK_CROSSING_NORMAL, drop);
|
|
|
|
|
gtk_drop_end_event (drop);
|
|
|
|
|
}
|
2017-03-31 15:38:38 +00:00
|
|
|
|
break;
|
2017-05-04 11:45:30 +00:00
|
|
|
|
case GDK_ENTER_NOTIFY:
|
2020-02-19 03:44:41 +00:00
|
|
|
|
case GDK_DRAG_ENTER:
|
|
|
|
|
case GDK_DRAG_MOTION:
|
|
|
|
|
case GDK_DROP_START:
|
2017-03-31 15:38:38 +00:00
|
|
|
|
case GDK_TOUCH_BEGIN:
|
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
case GDK_MOTION_NOTIFY:
|
2019-02-05 14:13:01 +00:00
|
|
|
|
target = gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device, sequence);
|
|
|
|
|
|
|
|
|
|
if (!target)
|
2020-05-15 06:22:04 +00:00
|
|
|
|
target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT);
|
2019-02-05 14:13:01 +00:00
|
|
|
|
|
|
|
|
|
if (!target)
|
2019-03-17 23:41:26 +00:00
|
|
|
|
target = GTK_WIDGET (native);
|
2019-02-05 14:13:01 +00:00
|
|
|
|
|
2017-03-31 15:38:38 +00:00
|
|
|
|
old_target = update_pointer_focus_state (toplevel, event, target);
|
2017-05-24 23:50:38 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
if (type == GDK_MOTION_NOTIFY || type == GDK_ENTER_NOTIFY)
|
2017-05-24 23:50:38 +00:00
|
|
|
|
{
|
2017-05-24 23:57:22 +00:00
|
|
|
|
if (!gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device,
|
|
|
|
|
sequence))
|
|
|
|
|
{
|
2020-02-19 03:44:41 +00:00
|
|
|
|
gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, old_target, target,
|
|
|
|
|
event, GDK_CROSSING_NORMAL, NULL);
|
2017-05-24 23:57:22 +00:00
|
|
|
|
}
|
2017-05-24 23:50:38 +00:00
|
|
|
|
|
|
|
|
|
gtk_window_maybe_update_cursor (toplevel, NULL, device);
|
|
|
|
|
}
|
2020-02-29 02:47:17 +00:00
|
|
|
|
else if ((old_target != target) &&
|
|
|
|
|
(type == GDK_DRAG_ENTER || type == GDK_DRAG_MOTION || type == GDK_DROP_START))
|
2020-02-19 03:44:41 +00:00
|
|
|
|
{
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
GdkDrop *drop = gdk_dnd_event_get_drop (event);
|
2020-02-29 02:47:17 +00:00
|
|
|
|
gtk_drop_begin_event (drop, type);
|
2020-02-19 03:44:41 +00:00
|
|
|
|
gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_DROP, old_target, target,
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
event, GDK_CROSSING_NORMAL, gdk_dnd_event_get_drop (event));
|
2020-02-29 02:47:17 +00:00
|
|
|
|
gtk_drop_end_event (drop);
|
2020-02-19 03:44:41 +00:00
|
|
|
|
}
|
|
|
|
|
else if (type == GDK_TOUCH_BEGIN)
|
2020-11-12 16:31:52 +00:00
|
|
|
|
{
|
|
|
|
|
gtk_window_set_pointer_focus_grab (toplevel, device, sequence, target);
|
|
|
|
|
set_widget_active_state (target, FALSE);
|
|
|
|
|
}
|
2017-03-31 15:55:49 +00:00
|
|
|
|
|
2017-03-31 15:38:38 +00:00
|
|
|
|
/* Let it take the effective pointer focus anyway, as it may change due
|
|
|
|
|
* to implicit grabs.
|
|
|
|
|
*/
|
|
|
|
|
target = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
2017-03-31 15:55:49 +00:00
|
|
|
|
target = gtk_window_lookup_effective_pointer_focus_widget (toplevel,
|
|
|
|
|
device,
|
|
|
|
|
sequence);
|
2020-11-19 19:12:58 +00:00
|
|
|
|
has_implicit =
|
|
|
|
|
gtk_window_lookup_pointer_focus_implicit_grab (toplevel,
|
|
|
|
|
device,
|
|
|
|
|
sequence) != NULL;
|
2020-12-08 22:13:50 +00:00
|
|
|
|
modifiers = gdk_event_get_modifier_state (event);
|
2020-11-19 19:12:58 +00:00
|
|
|
|
|
2020-12-08 22:13:50 +00:00
|
|
|
|
if (type == GDK_BUTTON_RELEASE &&
|
2020-12-09 15:48:09 +00:00
|
|
|
|
gtk_popcount (modifiers & (GDK_BUTTON1_MASK |
|
|
|
|
|
GDK_BUTTON2_MASK |
|
|
|
|
|
GDK_BUTTON3_MASK |
|
|
|
|
|
GDK_BUTTON4_MASK |
|
|
|
|
|
GDK_BUTTON5_MASK)) == 1)
|
2017-05-24 23:57:22 +00:00
|
|
|
|
{
|
2020-05-15 06:22:04 +00:00
|
|
|
|
GtkWidget *new_target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT);
|
2020-09-19 20:45:56 +00:00
|
|
|
|
|
2020-12-08 22:13:50 +00:00
|
|
|
|
gtk_window_set_pointer_focus_grab (toplevel, device, sequence, NULL);
|
|
|
|
|
|
2018-10-04 11:08:14 +00:00
|
|
|
|
if (new_target == NULL)
|
|
|
|
|
new_target = GTK_WIDGET (toplevel);
|
2020-09-19 20:45:56 +00:00
|
|
|
|
|
2020-02-19 03:44:41 +00:00
|
|
|
|
gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, target, new_target,
|
|
|
|
|
event, GDK_CROSSING_UNGRAB, NULL);
|
2017-05-24 23:57:22 +00:00
|
|
|
|
gtk_window_maybe_update_cursor (toplevel, NULL, device);
|
2020-09-19 20:45:56 +00:00
|
|
|
|
update_pointer_focus_state (toplevel, event, new_target);
|
2017-05-24 23:57:22 +00:00
|
|
|
|
}
|
2020-12-08 22:13:50 +00:00
|
|
|
|
else if (type == GDK_BUTTON_PRESS)
|
|
|
|
|
{
|
|
|
|
|
gtk_window_set_pointer_focus_grab (toplevel, device,
|
|
|
|
|
sequence, target);
|
|
|
|
|
}
|
2019-01-25 04:39:04 +00:00
|
|
|
|
|
2020-11-19 19:12:58 +00:00
|
|
|
|
if (type == GDK_BUTTON_PRESS)
|
|
|
|
|
set_widget_active_state (target, FALSE);
|
|
|
|
|
else if (has_implicit)
|
|
|
|
|
set_widget_active_state (target, TRUE);
|
2019-01-25 04:39:04 +00:00
|
|
|
|
|
2017-03-31 15:55:49 +00:00
|
|
|
|
break;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
case GDK_SCROLL:
|
|
|
|
|
case GDK_TOUCHPAD_PINCH:
|
|
|
|
|
case GDK_TOUCHPAD_SWIPE:
|
|
|
|
|
break;
|
2020-05-12 08:36:18 +00:00
|
|
|
|
case GDK_GRAB_BROKEN:
|
2020-11-14 09:48:04 +00:00
|
|
|
|
if (gdk_grab_broken_event_get_implicit (event))
|
|
|
|
|
{
|
|
|
|
|
target = gtk_window_lookup_effective_pointer_focus_widget (toplevel,
|
|
|
|
|
device,
|
|
|
|
|
sequence);
|
|
|
|
|
set_widget_active_state (target, TRUE);
|
|
|
|
|
}
|
2020-05-12 08:36:18 +00:00
|
|
|
|
break;
|
2017-03-31 15:38:38 +00:00
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!target)
|
|
|
|
|
target = gtk_window_lookup_effective_pointer_focus_widget (toplevel,
|
|
|
|
|
device,
|
|
|
|
|
sequence);
|
|
|
|
|
return target ? target : old_target;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-17 23:41:26 +00:00
|
|
|
|
static GtkWidget *
|
|
|
|
|
handle_key_event (GdkEvent *event)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *event_widget;
|
|
|
|
|
GtkWidget *focus_widget;
|
|
|
|
|
|
|
|
|
|
event_widget = gtk_get_event_widget (event);
|
|
|
|
|
|
|
|
|
|
focus_widget = gtk_root_get_focus (gtk_widget_get_root (event_widget));
|
|
|
|
|
return focus_widget ? focus_widget : event_widget;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-22 13:31:36 +00:00
|
|
|
|
static gboolean
|
|
|
|
|
is_transient_for (GtkWindow *child,
|
|
|
|
|
GtkWindow *parent)
|
|
|
|
|
{
|
|
|
|
|
GtkWindow *transient_for;
|
|
|
|
|
|
|
|
|
|
transient_for = gtk_window_get_transient_for (child);
|
|
|
|
|
|
|
|
|
|
while (transient_for)
|
|
|
|
|
{
|
|
|
|
|
if (transient_for == parent)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
transient_for = gtk_window_get_transient_for (transient_for);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 22:32:12 +00:00
|
|
|
|
void
|
1998-12-15 07:32:11 +00:00
|
|
|
|
gtk_main_do_event (GdkEvent *event)
|
1997-11-24 22:37:52 +00:00
|
|
|
|
{
|
|
|
|
|
GtkWidget *event_widget;
|
2019-01-29 04:33:38 +00:00
|
|
|
|
GtkWidget *target_widget;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
GtkWidget *grab_widget = NULL;
|
2001-06-14 21:44:01 +00:00
|
|
|
|
GtkWindowGroup *window_group;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
GdkEvent *rewritten_event = NULL;
|
1997-12-18 02:17:14 +00:00
|
|
|
|
GList *tmp_list;
|
1998-12-15 07:32:11 +00:00
|
|
|
|
|
2019-02-24 04:06:00 +00:00
|
|
|
|
if (gtk_inspector_handle_event (event))
|
|
|
|
|
return;
|
|
|
|
|
|
1998-12-15 07:32:11 +00:00
|
|
|
|
/* Find the widget which got the event. We store the widget
|
2018-03-20 10:40:08 +00:00
|
|
|
|
* in the user_data field of GdkSurface's. Ignore the event
|
2019-01-29 04:29:57 +00:00
|
|
|
|
* if we don't have a widget for it.
|
1998-12-15 07:32:11 +00:00
|
|
|
|
*/
|
|
|
|
|
event_widget = gtk_get_event_widget (event);
|
|
|
|
|
if (!event_widget)
|
2017-12-13 23:43:19 +00:00
|
|
|
|
return;
|
2002-03-02 20:37:07 +00:00
|
|
|
|
|
2019-01-29 04:33:38 +00:00
|
|
|
|
target_widget = event_widget;
|
|
|
|
|
|
2020-04-15 18:56:32 +00:00
|
|
|
|
/* We propagate key events from the root, even if they are
|
|
|
|
|
* delivered to a popup surface.
|
|
|
|
|
*
|
|
|
|
|
* If pointer or keyboard grabs are in effect, munge the events
|
2002-03-02 20:37:07 +00:00
|
|
|
|
* so that each window group looks like a separate app.
|
|
|
|
|
*/
|
2020-04-15 18:56:32 +00:00
|
|
|
|
if (is_key_event (event))
|
|
|
|
|
rewritten_event = rewrite_event_for_toplevel (event);
|
|
|
|
|
else
|
|
|
|
|
rewritten_event = rewrite_event_for_grabs (event);
|
2002-03-02 20:37:07 +00:00
|
|
|
|
if (rewritten_event)
|
|
|
|
|
{
|
|
|
|
|
event = rewritten_event;
|
2019-01-29 04:33:38 +00:00
|
|
|
|
target_widget = gtk_get_event_widget (event);
|
2002-03-02 20:37:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-05 17:21:40 +00:00
|
|
|
|
/* Push the event onto a stack of current events for
|
|
|
|
|
* gtk_current_event_get().
|
|
|
|
|
*/
|
|
|
|
|
current_events = g_list_prepend (current_events, event);
|
|
|
|
|
|
2017-05-04 11:48:27 +00:00
|
|
|
|
if (is_pointing_event (event))
|
2018-08-24 06:46:54 +00:00
|
|
|
|
{
|
|
|
|
|
target_widget = handle_pointing_event (event);
|
|
|
|
|
}
|
2019-03-17 23:41:26 +00:00
|
|
|
|
else if (is_key_event (event))
|
2018-03-07 16:59:22 +00:00
|
|
|
|
{
|
2019-03-17 23:41:26 +00:00
|
|
|
|
target_widget = handle_key_event (event);
|
2018-03-07 16:59:22 +00:00
|
|
|
|
}
|
2017-05-04 11:48:27 +00:00
|
|
|
|
|
2019-01-29 04:33:38 +00:00
|
|
|
|
if (!target_widget)
|
2017-05-04 11:48:27 +00:00
|
|
|
|
goto cleanup;
|
|
|
|
|
|
2019-01-29 04:33:38 +00:00
|
|
|
|
window_group = gtk_main_get_window_group (target_widget);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
2020-02-28 21:27:42 +00:00
|
|
|
|
/* check whether there is a grab in effect... */
|
|
|
|
|
grab_widget = gtk_window_group_get_current_grab (window_group);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
2010-06-15 17:06:51 +00:00
|
|
|
|
/* If the grab widget is an ancestor of the event widget
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* then we send the event to the original event widget.
|
2020-06-22 13:31:36 +00:00
|
|
|
|
* This is the key to implementing modality. This also applies
|
|
|
|
|
* across windows that are directly or indirectly transient-for
|
|
|
|
|
* the modal one.
|
2010-06-15 17:06:51 +00:00
|
|
|
|
*/
|
|
|
|
|
if (!grab_widget ||
|
2020-02-18 03:11:56 +00:00
|
|
|
|
((gtk_widget_is_sensitive (target_widget) || gdk_event_get_event_type (event) == GDK_SCROLL) &&
|
2020-06-22 13:31:36 +00:00
|
|
|
|
gtk_widget_is_ancestor (target_widget, grab_widget)) ||
|
|
|
|
|
(GTK_IS_WINDOW (grab_widget) &&
|
2020-06-26 12:19:32 +00:00
|
|
|
|
GTK_IS_WINDOW (event_widget) &&
|
2020-06-22 13:31:36 +00:00
|
|
|
|
grab_widget != event_widget &&
|
|
|
|
|
is_transient_for (GTK_WINDOW (event_widget), GTK_WINDOW (grab_widget))))
|
2019-01-29 04:33:38 +00:00
|
|
|
|
grab_widget = target_widget;
|
2015-06-15 12:07:40 +00:00
|
|
|
|
|
2020-05-22 16:25:23 +00:00
|
|
|
|
g_object_ref (target_widget);
|
|
|
|
|
|
1998-12-15 07:32:11 +00:00
|
|
|
|
/* Not all events get sent to the grabbing widget.
|
|
|
|
|
* The delete, destroy, expose, focus change and resize
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* events still get sent to the event widget because
|
|
|
|
|
* 1) these events have no meaning for the grabbing widget
|
|
|
|
|
* and 2) redirecting these events to the grabbing widget
|
|
|
|
|
* could cause the display to be messed up.
|
|
|
|
|
*
|
1998-12-15 07:32:11 +00:00
|
|
|
|
* Drag events are also not redirected, since it isn't
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* clear what the semantics of that would be.
|
1997-11-24 22:37:52 +00:00
|
|
|
|
*/
|
2020-02-18 03:11:56 +00:00
|
|
|
|
switch ((guint)gdk_event_get_event_type (event))
|
1997-11-24 22:37:52 +00:00
|
|
|
|
{
|
1998-12-15 07:32:11 +00:00
|
|
|
|
case GDK_DELETE:
|
2018-06-07 14:47:44 +00:00
|
|
|
|
if (!gtk_window_group_get_current_grab (window_group) ||
|
2019-03-17 23:41:26 +00:00
|
|
|
|
GTK_WIDGET (gtk_widget_get_root (gtk_window_group_get_current_grab (window_group))) == target_widget)
|
2018-06-07 14:47:44 +00:00
|
|
|
|
{
|
2020-05-09 14:33:02 +00:00
|
|
|
|
if (GTK_IS_WINDOW (target_widget) &&
|
2019-01-29 04:33:38 +00:00
|
|
|
|
!gtk_window_emit_close_request (GTK_WINDOW (target_widget)))
|
2020-05-09 14:33:02 +00:00
|
|
|
|
gtk_window_destroy (GTK_WINDOW (target_widget));
|
2018-06-07 14:47:44 +00:00
|
|
|
|
}
|
1998-12-15 07:32:11 +00:00
|
|
|
|
break;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2018-06-07 14:47:44 +00:00
|
|
|
|
case GDK_FOCUS_CHANGE:
|
2020-10-09 03:06:07 +00:00
|
|
|
|
{
|
|
|
|
|
GtkWidget *root = GTK_WIDGET (gtk_widget_get_root (target_widget));
|
|
|
|
|
if (!_gtk_widget_captured_event (root, event, root))
|
|
|
|
|
gtk_widget_event (root, event, root);
|
|
|
|
|
}
|
1998-12-15 07:32:11 +00:00
|
|
|
|
break;
|
1999-01-28 00:57:18 +00:00
|
|
|
|
|
1998-12-15 07:32:11 +00:00
|
|
|
|
case GDK_KEY_PRESS:
|
|
|
|
|
case GDK_KEY_RELEASE:
|
2014-06-29 22:52:50 +00:00
|
|
|
|
case GDK_SCROLL:
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
|
case GDK_TOUCH_BEGIN:
|
1998-12-15 07:32:11 +00:00
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
|
case GDK_PROXIMITY_IN:
|
|
|
|
|
case GDK_PROXIMITY_OUT:
|
2011-12-28 23:06:45 +00:00
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
2015-07-09 16:47:02 +00:00
|
|
|
|
case GDK_TOUCHPAD_SWIPE:
|
|
|
|
|
case GDK_TOUCHPAD_PINCH:
|
2016-08-04 17:17:21 +00:00
|
|
|
|
case GDK_PAD_BUTTON_PRESS:
|
|
|
|
|
case GDK_PAD_BUTTON_RELEASE:
|
|
|
|
|
case GDK_PAD_RING:
|
|
|
|
|
case GDK_PAD_STRIP:
|
|
|
|
|
case GDK_PAD_GROUP_MODE:
|
2020-05-12 08:36:18 +00:00
|
|
|
|
case GDK_GRAB_BROKEN:
|
2017-05-29 12:55:37 +00:00
|
|
|
|
gtk_propagate_event (grab_widget, event);
|
1998-12-15 07:32:11 +00:00
|
|
|
|
break;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
1998-12-15 07:32:11 +00:00
|
|
|
|
case GDK_ENTER_NOTIFY:
|
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
2020-02-29 02:47:17 +00:00
|
|
|
|
case GDK_DRAG_ENTER:
|
|
|
|
|
case GDK_DRAG_LEAVE:
|
2017-04-13 13:42:48 +00:00
|
|
|
|
/* Crossing event propagation happens during picking */
|
1998-12-15 07:32:11 +00:00
|
|
|
|
break;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
1998-12-15 07:32:11 +00:00
|
|
|
|
case GDK_DRAG_MOTION:
|
|
|
|
|
case GDK_DROP_START:
|
2020-02-29 02:47:17 +00:00
|
|
|
|
{
|
Restructure the GdkEvent type hierarchy
GdkEvent has been a "I-can't-believe-this-is-not-OOP" type for ages,
using a union of sub-types. This has always been problematic when it
comes to implementing accessor functions: either you get generic API
that takes a GdkEvent and uses a massive switch() to determine which
event types have the data you're looking for; or you create namespaced
accessors, but break language bindings horribly, as boxed types cannot
have derived types.
The recent conversion of GskRenderNode (which had similar issues) to
GTypeInstance, and the fact that GdkEvent is now a completely opaque
type, provide us with the chance of moving GdkEvent to GTypeInstance,
and have sub-types for GdkEvent.
The change from boxed type to GTypeInstance is pretty small, all things
considered, but ends up cascading to a larger commit, as we still have
backends and code in GTK trying to access GdkEvent structures directly.
Additionally, the naming of the public getter functions requires
renaming all the data structures to conform to the namespace/type-name
pattern.
2020-04-16 16:23:36 +00:00
|
|
|
|
GdkDrop *drop = gdk_dnd_event_get_drop (event);
|
2020-02-29 02:47:17 +00:00
|
|
|
|
gtk_drop_begin_event (drop, gdk_event_get_event_type (event));
|
|
|
|
|
gtk_propagate_event (target_widget, event);
|
|
|
|
|
gtk_drop_end_event (drop);
|
|
|
|
|
}
|
1998-12-15 07:32:11 +00:00
|
|
|
|
break;
|
2020-01-06 04:49:22 +00:00
|
|
|
|
|
2017-10-06 19:19:42 +00:00
|
|
|
|
case GDK_EVENT_LAST:
|
2001-04-29 03:08:32 +00:00
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
break;
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|
2007-02-06 10:25:21 +00:00
|
|
|
|
|
2020-02-16 01:47:23 +00:00
|
|
|
|
_gtk_tooltip_handle_event (target_widget, event);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2020-05-22 16:25:23 +00:00
|
|
|
|
g_object_unref (target_widget);
|
|
|
|
|
|
2015-06-05 17:21:40 +00:00
|
|
|
|
cleanup:
|
1998-12-15 07:32:11 +00:00
|
|
|
|
tmp_list = current_events;
|
|
|
|
|
current_events = g_list_remove_link (current_events, tmp_list);
|
|
|
|
|
g_list_free_1 (tmp_list);
|
2002-03-02 20:37:07 +00:00
|
|
|
|
|
|
|
|
|
if (rewritten_event)
|
2020-02-15 20:07:24 +00:00
|
|
|
|
gdk_event_unref (rewritten_event);
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-14 21:44:01 +00:00
|
|
|
|
static GtkWindowGroup *
|
2011-01-04 22:32:12 +00:00
|
|
|
|
gtk_main_get_window_group (GtkWidget *widget)
|
2001-06-14 21:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
GtkWidget *toplevel = NULL;
|
|
|
|
|
|
|
|
|
|
if (widget)
|
2019-05-20 04:47:50 +00:00
|
|
|
|
toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
|
2001-06-14 21:44:01 +00:00
|
|
|
|
|
2008-02-06 09:53:34 +00:00
|
|
|
|
if (GTK_IS_WINDOW (toplevel))
|
2006-01-10 04:33:30 +00:00
|
|
|
|
return gtk_window_get_group (GTK_WINDOW (toplevel));
|
2001-06-14 21:44:01 +00:00
|
|
|
|
else
|
2006-01-10 04:33:30 +00:00
|
|
|
|
return gtk_window_get_group (NULL);
|
2001-06-14 21:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_grab_notify (GtkWindowGroup *group,
|
2011-01-04 22:32:12 +00:00
|
|
|
|
GtkWidget *old_grab_widget,
|
|
|
|
|
GtkWidget *new_grab_widget,
|
|
|
|
|
gboolean from_grab)
|
2001-06-14 21:44:01 +00:00
|
|
|
|
{
|
|
|
|
|
GList *toplevels;
|
|
|
|
|
|
2006-04-06 01:58:38 +00:00
|
|
|
|
if (old_grab_widget == new_grab_widget)
|
|
|
|
|
return;
|
|
|
|
|
|
2001-06-14 21:44:01 +00:00
|
|
|
|
g_object_ref (group);
|
|
|
|
|
|
|
|
|
|
toplevels = gtk_window_list_toplevels ();
|
|
|
|
|
g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
2001-06-14 21:44:01 +00:00
|
|
|
|
while (toplevels)
|
|
|
|
|
{
|
|
|
|
|
GtkWindow *toplevel = toplevels->data;
|
|
|
|
|
toplevels = g_list_delete_link (toplevels, toplevels);
|
|
|
|
|
|
2020-06-24 15:19:57 +00:00
|
|
|
|
gtk_window_grab_notify (toplevel,
|
|
|
|
|
old_grab_widget,
|
|
|
|
|
new_grab_widget,
|
|
|
|
|
from_grab);
|
2001-06-14 21:44:01 +00:00
|
|
|
|
g_object_unref (toplevel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_object_unref (group);
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 22:32:12 +00:00
|
|
|
|
/**
|
2011-02-03 14:20:23 +00:00
|
|
|
|
* gtk_grab_add: (method)
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* @widget: The widget that grabs keyboard and pointer events
|
|
|
|
|
*
|
|
|
|
|
* Makes @widget the current grabbed widget.
|
|
|
|
|
*
|
|
|
|
|
* This means that interaction with other widgets in the same
|
|
|
|
|
* application is blocked and mouse as well as keyboard events
|
|
|
|
|
* are delivered to this widget.
|
|
|
|
|
*
|
|
|
|
|
* If @widget is not sensitive, it is not set as the current
|
|
|
|
|
* grabbed widget and this function does nothing.
|
|
|
|
|
*/
|
1997-11-24 22:37:52 +00:00
|
|
|
|
void
|
|
|
|
|
gtk_grab_add (GtkWidget *widget)
|
|
|
|
|
{
|
2001-06-14 21:44:01 +00:00
|
|
|
|
GtkWindowGroup *group;
|
2006-04-06 01:58:38 +00:00
|
|
|
|
GtkWidget *old_grab_widget;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
1998-01-19 08:23:24 +00:00
|
|
|
|
g_return_if_fail (widget != NULL);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2010-02-27 04:24:24 +00:00
|
|
|
|
if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
|
1998-01-19 08:23:24 +00:00
|
|
|
|
{
|
2010-04-11 21:19:42 +00:00
|
|
|
|
_gtk_widget_set_has_grab (widget, TRUE);
|
2010-12-18 01:41:16 +00:00
|
|
|
|
|
2001-06-14 21:44:01 +00:00
|
|
|
|
group = gtk_main_get_window_group (widget);
|
|
|
|
|
|
2010-12-18 01:41:16 +00:00
|
|
|
|
old_grab_widget = gtk_window_group_get_current_grab (group);
|
2006-04-06 01:58:38 +00:00
|
|
|
|
|
2002-10-09 00:38:22 +00:00
|
|
|
|
g_object_ref (widget);
|
2010-12-18 01:41:16 +00:00
|
|
|
|
_gtk_window_group_add_grab (group, widget);
|
2001-06-14 21:44:01 +00:00
|
|
|
|
|
2020-06-23 10:15:00 +00:00
|
|
|
|
gtk_grab_notify (group, old_grab_widget, widget, TRUE);
|
1998-01-19 08:23:24 +00:00
|
|
|
|
}
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 22:32:12 +00:00
|
|
|
|
/**
|
2011-02-03 14:20:23 +00:00
|
|
|
|
* gtk_grab_remove: (method)
|
2011-01-04 22:32:12 +00:00
|
|
|
|
* @widget: The widget which gives up the grab
|
|
|
|
|
*
|
|
|
|
|
* Removes the grab from the given widget.
|
|
|
|
|
*
|
|
|
|
|
* You have to pair calls to gtk_grab_add() and gtk_grab_remove().
|
|
|
|
|
*
|
|
|
|
|
* If @widget does not have the grab, this function does nothing.
|
|
|
|
|
*/
|
1997-11-24 22:37:52 +00:00
|
|
|
|
void
|
|
|
|
|
gtk_grab_remove (GtkWidget *widget)
|
|
|
|
|
{
|
2001-06-14 21:44:01 +00:00
|
|
|
|
GtkWindowGroup *group;
|
2006-04-06 01:58:38 +00:00
|
|
|
|
GtkWidget *new_grab_widget;
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
1998-01-19 08:23:24 +00:00
|
|
|
|
g_return_if_fail (widget != NULL);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2010-01-04 02:07:11 +00:00
|
|
|
|
if (gtk_widget_has_grab (widget))
|
1998-01-19 08:23:24 +00:00
|
|
|
|
{
|
2010-04-11 21:19:42 +00:00
|
|
|
|
_gtk_widget_set_has_grab (widget, FALSE);
|
2001-06-14 21:44:01 +00:00
|
|
|
|
|
|
|
|
|
group = gtk_main_get_window_group (widget);
|
2010-12-18 01:41:16 +00:00
|
|
|
|
_gtk_window_group_remove_grab (group, widget);
|
|
|
|
|
new_grab_widget = gtk_window_group_get_current_grab (group);
|
2001-06-14 21:44:01 +00:00
|
|
|
|
|
2020-06-23 10:15:00 +00:00
|
|
|
|
gtk_grab_notify (group, widget, new_grab_widget, FALSE);
|
2010-12-18 01:41:16 +00:00
|
|
|
|
|
2006-04-06 01:58:38 +00:00
|
|
|
|
g_object_unref (widget);
|
1998-01-19 08:23:24 +00:00
|
|
|
|
}
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
Remove g_convert (moved to glib) and now useless utf_to_latin1()
Thu Sep 14 12:21:12 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtktexttypes.[ch]: Remove g_convert (moved to
glib) and now useless utf_to_latin1() latin1_to_utf()
* gtk/gtktextview.[ch]: Change ::move_insert and
::delete_text action signals to ::move and ::delete;
create the signals with the right enumeration type,
not GTK_TYPE_ENUM so that bindings work. Add C-d, M-d,
C-v bindings, change Home, End to move to beginning/end
of line, Add C-Home C-End to move to beginning/end
of buffer. Change ::cut_text to ::cut_clipboard, etc;
combine ::scroll_text into ::move; use new GtkSelectionData
functions to simplify DND text handling.
* gtk/gtkenums.h gtk/gtktextview.h: Move movement,
deletion enumerations here, rename enumeration values to
be consistently plural.
* gtk/gtktextbuffer.c: Use new clipboard interfaces
for cut/copy/paste and primary selection.
* gtk/gtktextbuffer.[ch]: Remove excess time and
'interactive' arguments from cut/copy/paste;
rename cut to cut_clipboard, etc; remove
gtk_text_buffer_get_clipboard_contents().
* gtk/gtktextlayout.[ch]: Add
gtk_text_layout_move_iter_to_line_end() to move the iter to
line ends.
* gtk/gtkselection.[ch] (gtk_selection_data_set/get_text):
Functions to set or get a UTF-8 string on the selection
data.
* gtk/gtkclipboard.[ch]: New, simplified selection handling
interfaces.
* gtk/gtkinvisible.c (gtk_invisible_new): Realize newly
created widgets - one of these is useless if we don't.
* gtk/gtkselection.[ch] (gtk_selection_clear_targets): Export
a public function clear all targets registered for the
widget.
* gtk/gtkselection.c (gtk_selection_owner_set) docs/Changes-2.0.txt:
Never call gtk_widget_realize() - that was just asking
for bizarre side-effects.
* gtk/gtkselection.c (gtk_selection_owner_set): Call
gdk_selection_owner_set even if the widget is the
same so that we reliably update the timestamp on
the server.
* gdk/x11/gdkevents-x11.c gdk/x11/gdkx.h: Add a
gdk_x11_get_server_time() function.
* gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.h
gdk/x11/gdkselection-x11.c gdk/x11/gdkwindow-x11.h:
Add some tricky filtering on serial numbers for
selection clear events to fix up long-standard
race condition FIXME's in gtkselection.c.
* gdk/gdkproperty.h gdk/x11/gdkselection-x11.h: Add
routines to convert from utf8 to compound text or
STRING and from a text property to UTF-8.
* gtk/gtkmain.[ch] (gtk_get_current_event_time): Add
a convenience function gdk_get_current_event_time().
* gtk/gtkselection.c (gtk_selection_data_copy/free): Copy
and free selection_data->data properly
2000-09-14 16:41:20 +00:00
|
|
|
|
guint32
|
|
|
|
|
gtk_get_current_event_time (void)
|
|
|
|
|
{
|
|
|
|
|
if (current_events)
|
|
|
|
|
return gdk_event_get_time (current_events->data);
|
|
|
|
|
else
|
|
|
|
|
return GDK_CURRENT_TIME;
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-03 01:09:41 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_get_event_widget:
|
|
|
|
|
* @event: a #GdkEvent
|
|
|
|
|
*
|
|
|
|
|
* If @event is %NULL or the event was not associated with any widget,
|
|
|
|
|
* returns %NULL, otherwise returns the widget that received the event
|
|
|
|
|
* originally.
|
2011-01-04 22:32:12 +00:00
|
|
|
|
*
|
2015-09-15 07:19:31 +00:00
|
|
|
|
* Returns: (transfer none) (nullable): the widget that originally
|
2010-09-21 04:18:11 +00:00
|
|
|
|
* received @event, or %NULL
|
2011-01-04 22:32:12 +00:00
|
|
|
|
*/
|
2020-02-18 03:11:56 +00:00
|
|
|
|
GtkWidget *
|
2020-02-16 16:09:02 +00:00
|
|
|
|
gtk_get_event_widget (GdkEvent *event)
|
1997-11-24 22:37:52 +00:00
|
|
|
|
{
|
2020-02-18 03:11:56 +00:00
|
|
|
|
GdkSurface *surface;
|
1998-01-30 23:47:09 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
surface = gdk_event_get_surface (event);
|
|
|
|
|
if (surface && !gdk_surface_is_destroyed (surface))
|
2020-08-13 23:21:05 +00:00
|
|
|
|
return GTK_WIDGET (gtk_native_get_for_surface (surface));
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2020-02-18 03:11:56 +00:00
|
|
|
|
return NULL;
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 08:32:57 +00:00
|
|
|
|
gboolean
|
|
|
|
|
gtk_propagate_event_internal (GtkWidget *widget,
|
|
|
|
|
GdkEvent *event,
|
|
|
|
|
GtkWidget *topmost)
|
2011-02-08 13:49:31 +00:00
|
|
|
|
{
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int handled_event = FALSE;
|
2020-02-16 07:20:34 +00:00
|
|
|
|
GtkWidget *target = widget;
|
2020-07-02 18:50:14 +00:00
|
|
|
|
GtkWidgetStack widget_array;
|
2020-04-10 06:17:46 +00:00
|
|
|
|
int i;
|
|
|
|
|
|
2020-05-08 08:32:57 +00:00
|
|
|
|
/* First, propagate event down */
|
2020-07-02 18:50:14 +00:00
|
|
|
|
gtk_widget_stack_init (&widget_array);
|
|
|
|
|
gtk_widget_stack_append (&widget_array, g_object_ref (widget));
|
2011-02-08 13:49:31 +00:00
|
|
|
|
|
2020-04-10 06:17:46 +00:00
|
|
|
|
for (;;)
|
2011-02-08 13:49:31 +00:00
|
|
|
|
{
|
2020-04-29 06:15:23 +00:00
|
|
|
|
widget = _gtk_widget_get_parent (widget);
|
2011-02-08 13:49:31 +00:00
|
|
|
|
if (!widget)
|
|
|
|
|
break;
|
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
gtk_widget_stack_append (&widget_array, g_object_ref (widget));
|
2011-02-08 13:49:31 +00:00
|
|
|
|
|
|
|
|
|
if (widget == topmost)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
i = gtk_widget_stack_get_size (&widget_array) - 1;
|
2020-04-10 06:17:46 +00:00
|
|
|
|
for (;;)
|
2011-02-08 13:49:31 +00:00
|
|
|
|
{
|
2020-07-02 18:50:14 +00:00
|
|
|
|
widget = gtk_widget_stack_get (&widget_array, i);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2020-04-29 06:15:23 +00:00
|
|
|
|
if (!_gtk_widget_is_sensitive (widget))
|
2012-11-22 12:37:58 +00:00
|
|
|
|
{
|
|
|
|
|
/* stop propagating on SCROLL, but don't handle the event, so it
|
|
|
|
|
* can propagate up again and reach its handling widget
|
|
|
|
|
*/
|
2020-02-18 03:11:56 +00:00
|
|
|
|
if (gdk_event_get_event_type (event) == GDK_SCROLL)
|
2012-11-22 12:37:58 +00:00
|
|
|
|
break;
|
|
|
|
|
else
|
|
|
|
|
handled_event = TRUE;
|
|
|
|
|
}
|
2020-04-29 06:15:23 +00:00
|
|
|
|
else if (_gtk_widget_get_realized (widget))
|
2020-02-16 07:20:34 +00:00
|
|
|
|
handled_event = _gtk_widget_captured_event (widget, event, target);
|
2018-12-17 17:04:10 +00:00
|
|
|
|
|
2020-04-29 06:15:23 +00:00
|
|
|
|
handled_event |= !_gtk_widget_get_realized (widget);
|
2020-04-10 06:17:46 +00:00
|
|
|
|
|
|
|
|
|
if (handled_event)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
i--;
|
2011-02-08 13:49:31 +00:00
|
|
|
|
}
|
2020-04-10 06:17:46 +00:00
|
|
|
|
|
2020-05-08 08:32:57 +00:00
|
|
|
|
/* If not yet handled, also propagate down */
|
|
|
|
|
if (!handled_event)
|
|
|
|
|
{
|
|
|
|
|
/* Propagate event up the widget tree so that
|
|
|
|
|
* parents can see the button and motion
|
|
|
|
|
* events of the children.
|
|
|
|
|
*/
|
2020-07-02 18:50:14 +00:00
|
|
|
|
for (i = 0; i < gtk_widget_stack_get_size (&widget_array); i++)
|
2020-05-08 08:32:57 +00:00
|
|
|
|
{
|
2020-07-02 18:50:14 +00:00
|
|
|
|
widget = gtk_widget_stack_get (&widget_array, i);
|
1998-03-27 05:17:11 +00:00
|
|
|
|
|
2020-05-08 08:32:57 +00:00
|
|
|
|
/* Scroll events are special cased here because it
|
|
|
|
|
* feels wrong when scrolling a GtkViewport, say,
|
|
|
|
|
* to have children of the viewport eat the scroll
|
|
|
|
|
* event
|
|
|
|
|
*/
|
|
|
|
|
if (!_gtk_widget_is_sensitive (widget))
|
|
|
|
|
handled_event = gdk_event_get_event_type (event) != GDK_SCROLL;
|
|
|
|
|
else if (_gtk_widget_get_realized (widget))
|
|
|
|
|
handled_event = gtk_widget_event (widget, event, target);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2020-05-08 08:32:57 +00:00
|
|
|
|
handled_event |= !_gtk_widget_get_realized (widget);
|
2020-01-06 04:49:22 +00:00
|
|
|
|
|
2020-05-08 08:32:57 +00:00
|
|
|
|
if (handled_event)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-06 04:49:22 +00:00
|
|
|
|
|
2020-07-02 18:50:14 +00:00
|
|
|
|
gtk_widget_stack_clear (&widget_array);
|
2020-05-08 08:32:57 +00:00
|
|
|
|
return handled_event;
|
2017-05-29 12:55:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 13:49:31 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_propagate_event:
|
|
|
|
|
* @widget: a #GtkWidget
|
|
|
|
|
* @event: an event
|
|
|
|
|
*
|
|
|
|
|
* Sends an event to a widget, propagating the event to parent widgets
|
2017-05-29 12:55:37 +00:00
|
|
|
|
* if the event remains unhandled. This function will emit the event
|
|
|
|
|
* through all the hierarchy of @widget through all propagation phases.
|
2011-02-08 13:49:31 +00:00
|
|
|
|
*
|
2020-02-09 15:45:33 +00:00
|
|
|
|
* Events received by GTK from GDK normally begin at a #GtkRoot widget.
|
2011-02-08 13:49:31 +00:00
|
|
|
|
* Depending on the type of event, existence of modal dialogs, grabs, etc.,
|
|
|
|
|
* the event may be propagated; if so, this function is used.
|
|
|
|
|
*
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* All that said, you most likely don’t want to use any of these
|
2011-02-08 13:49:31 +00:00
|
|
|
|
* functions; synthesizing events is rarely needed. There are almost
|
|
|
|
|
* certainly better ways to achieve your goals. For example, use
|
2016-10-19 20:33:26 +00:00
|
|
|
|
* gtk_widget_queue_draw() instead
|
2011-02-08 13:49:31 +00:00
|
|
|
|
* of making up expose events.
|
2020-01-06 04:49:22 +00:00
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the event was handled
|
2011-02-08 13:49:31 +00:00
|
|
|
|
*/
|
2020-01-06 04:49:22 +00:00
|
|
|
|
gboolean
|
2011-02-08 13:49:31 +00:00
|
|
|
|
gtk_propagate_event (GtkWidget *widget,
|
|
|
|
|
GdkEvent *event)
|
|
|
|
|
{
|
2017-05-29 12:55:37 +00:00
|
|
|
|
GtkWindowGroup *window_group;
|
|
|
|
|
GtkWidget *event_widget, *topmost = NULL;
|
|
|
|
|
|
2020-01-06 04:49:22 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
|
g_return_val_if_fail (event != NULL, FALSE);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2017-05-29 12:55:37 +00:00
|
|
|
|
event_widget = gtk_get_event_widget (event);
|
|
|
|
|
window_group = gtk_main_get_window_group (event_widget);
|
2011-01-04 22:32:12 +00:00
|
|
|
|
|
2020-02-28 21:27:42 +00:00
|
|
|
|
/* check whether there is a grab in effect... */
|
|
|
|
|
topmost = gtk_window_group_get_current_grab (window_group);
|
2017-05-29 12:55:37 +00:00
|
|
|
|
|
2020-01-06 04:49:22 +00:00
|
|
|
|
return gtk_propagate_event_internal (widget, event, topmost);
|
1997-11-24 22:37:52 +00:00
|
|
|
|
}
|