* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
#include "gtkintl.h"
-#include "gtkaccelmap.h"
+#include "gtkaccelmapprivate.h"
#include "gtkbox.h"
#include "gtkclipboard.h"
#include "gtkdebug.h"
#include "gtkmodulesprivate.h"
#include "gtkprivate.h"
#include "gtkrecentmanager.h"
+#include "gtkresources.h"
#include "gtkselectionprivate.h"
#include "gtksettingsprivate.h"
#include "gtktooltip.h"
#include "gtkwidgetprivate.h"
#include "gtkwindowprivate.h"
+#include "a11y/gtkaccessibility.h"
/* Private type definitions
*/
{"printing", GTK_DEBUG_PRINTING},
{"builder", GTK_DEBUG_BUILDER},
{"size-request", GTK_DEBUG_SIZE_REQUEST},
+ {"no-css-cache", GTK_DEBUG_NO_CSS_CACHE}
};
#endif /* G_ENABLE_DEBUG */
#endif
}
-/* XXX: Remove me after getting rid of gail */
-extern void _gtk_accessibility_init (void);
-
static void
do_post_parse_initialization (int *argc,
char ***argv)
g_warning ("Whoever translated default:LTR did so wrongly.\n");
}
- /* do what the call to gtk_type_init() used to do */
- g_type_init ();
+ _gtk_register_resource ();
_gtk_accel_map_init ();
if (g_main_loop_is_running (main_loops->data))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
gdk_flush ();
}
if (gtk_main_loop_level == 0)
{
+ /* Keep this section in sync with gtk_application_shutdown() */
+
/* Try storing all clipboard data we have */
_gtk_clipboard_store_all ();
/* Synchronize the recent manager singleton */
_gtk_recent_manager_sync ();
+
+ _gtk_accessibility_shutdown ();
}
}
{
gboolean result;
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
result = g_main_context_pending (NULL);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
return result;
}
gboolean
gtk_main_iteration (void)
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_context_iteration (NULL, TRUE);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
if (main_loops)
return !g_main_loop_is_running (main_loops->data);
gboolean
gtk_main_iteration_do (gboolean blocking)
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_context_iteration (NULL, blocking);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
if (main_loops)
return !g_main_loop_is_running (main_loops->data);
new_window,
&event->motion.x, &event->motion.y);
break;
+ case GDK_TOUCH_BEGIN:
+ case GDK_TOUCH_UPDATE:
+ case GDK_TOUCH_END:
+ case GDK_TOUCH_CANCEL:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->touch.x, &event->touch.y);
+ break;
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
case GDK_PROXIMITY_IN:
case GDK_PROXIMITY_OUT:
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
+ case GDK_TOUCH_BEGIN:
+ case GDK_TOUCH_UPDATE:
+ case GDK_TOUCH_END:
+ case GDK_TOUCH_CANCEL:
display = gdk_window_get_display (event->any.window);
device = gdk_event_get_device (event);
* </para></listitem>
* <listitem><para>
* Find the widget which got the event. If the widget can't be determined
- * the event is thrown away unless it belongs to a INCR transaction. In that
- * case it is passed to gtk_selection_incr_event().
+ * the event is thrown away unless it belongs to a INCR transaction.
* </para></listitem>
* <listitem><para>
* Then the event is pushed onto a stack so you can query the currently
{
GtkWidget *event_widget;
GtkWidget *grab_widget = NULL;
+ GtkWidget *topmost_widget = NULL;
GtkWindowGroup *window_group;
GdkEvent *rewritten_event = NULL;
GdkDevice *device;
if (!grab_widget)
grab_widget = gtk_window_group_get_current_grab (window_group);
+ /* Find out the topmost widget where captured event propagation
+ * should start, which is the widget holding the GTK+ grab
+ * if any, otherwise it's left NULL and events are emitted
+ * from the toplevel (or topmost parentless parent).
+ */
+ if (grab_widget)
+ topmost_widget = grab_widget;
+
/* If the grab widget is an ancestor of the event widget
* then we send the event to the original event widget.
* This is the key to implementing modality.
*/
if (!grab_widget ||
- (gtk_widget_is_sensitive (event_widget) &&
+ ((gtk_widget_is_sensitive (event_widget) || event->type == GDK_SCROLL) &&
gtk_widget_is_ancestor (event_widget, grab_widget)))
grab_widget = event_widget;
case GDK_WINDOW_STATE:
case GDK_GRAB_BROKEN:
case GDK_DAMAGE:
- gtk_widget_event (event_widget, event);
+ if (!_gtk_widget_captured_event (event_widget, event))
+ gtk_widget_event (event_widget, event);
break;
case GDK_SCROLL:
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
- gtk_propagate_event (grab_widget, event);
+ case GDK_TOUCH_BEGIN:
+ if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
+ gtk_propagate_event (grab_widget, event);
break;
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
- if (key_snoopers)
- {
- if (gtk_invoke_key_snoopers (grab_widget, event))
- break;
- }
+ if (gtk_invoke_key_snoopers (grab_widget, event))
+ break;
/* make focus visible in a window that receives a key event */
{
window = gtk_widget_get_toplevel (grab_widget);
if (GTK_IS_WINDOW (window))
- gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
+ {
+ if (mnemonics_visible)
+ _gtk_window_set_auto_mnemonics_visible (GTK_WINDOW (window));
+ else
+ gtk_window_set_mnemonics_visible (GTK_WINDOW (window), FALSE);
+ }
}
}
/* else fall through */
case GDK_BUTTON_RELEASE:
case GDK_PROXIMITY_IN:
case GDK_PROXIMITY_OUT:
- gtk_propagate_event (grab_widget, event);
+ case GDK_TOUCH_UPDATE:
+ case GDK_TOUCH_END:
+ case GDK_TOUCH_CANCEL:
+ if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
+ gtk_propagate_event (grab_widget, event);
break;
case GDK_ENTER_NOTIFY:
- _gtk_widget_set_device_window (event_widget,
- gdk_event_get_device (event),
- event->any.window);
- if (gtk_widget_is_sensitive (grab_widget))
+ if (event->crossing.detail != GDK_NOTIFY_VIRTUAL &&
+ event->crossing.detail != GDK_NOTIFY_NONLINEAR_VIRTUAL)
+ _gtk_widget_set_device_window (event_widget,
+ gdk_event_get_device (event),
+ event->any.window);
+ if (gtk_widget_is_sensitive (grab_widget) &&
+ !_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
gtk_widget_event (grab_widget, event);
break;
case GDK_LEAVE_NOTIFY:
- _gtk_widget_set_device_window (event_widget,
- gdk_event_get_device (event),
- NULL);
- if (gtk_widget_is_sensitive (grab_widget))
+ if (event->crossing.detail != GDK_NOTIFY_VIRTUAL &&
+ event->crossing.detail != GDK_NOTIFY_NONLINEAR_VIRTUAL)
+ _gtk_widget_set_device_window (event_widget,
+ gdk_event_get_device (event),
+ NULL);
+ if (gtk_widget_is_sensitive (grab_widget) &&
+ !_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
gtk_widget_event (grab_widget, event);
break;
|| event->type == GDK_DRAG_ENTER
|| event->type == GDK_GRAB_BROKEN
|| event->type == GDK_MOTION_NOTIFY
+ || event->type == GDK_TOUCH_UPDATE
|| event->type == GDK_SCROLL)
{
_gtk_tooltip_handle_event (event);
/**
* gtk_device_grab_add:
* @widget: a #GtkWidget
- * @device: a #GtkDevice to grab on.
+ * @device: a #GdkDevice to grab on.
* @block_others: %TRUE to prevent other devices to interact with @widget.
*
* Adds a GTK+ grab on @device, so all the events on @device and its
*
* Returns: a unique id for this key snooper for use with
* gtk_key_snooper_remove().
+ *
+ * Deprecated: 3.4: Key snooping should not be done. Events should
+ * be handled by widgets.
*/
guint
gtk_key_snooper_install (GtkKeySnoopFunc snooper,
* @snooper_handler_id: Identifies the key snooper to remove
*
* Removes the key snooper function with the given id.
+ *
+ * Deprecated: 3.4: Key snooping should not be done. Events should
+ * be handled by widgets.
*/
void
gtk_key_snooper_remove (guint snooper_id)
GSList *slist;
gint return_val = FALSE;
+ return_val = _gtk_accessibility_key_snooper (grab_widget, (GdkEventKey *) event);
+
slist = key_snoopers;
while (slist && !return_val)
{
return widget;
}
-/**
- * gtk_propagate_event:
- * @widget: a #GtkWidget
- * @event: an event
- *
- * Sends an event to a widget, propagating the event to parent widgets
- * if the event remains unhandled.
- *
- * Events received by GTK+ from GDK normally begin in gtk_main_do_event().
- * Depending on the type of event, existence of modal dialogs, grabs, etc.,
- * the event may be propagated; if so, this function is used.
- *
- * gtk_propagate_event() calls gtk_widget_event() on each widget it
- * decides to send the event to. So gtk_widget_event() is the lowest-level
- * function; it simply emits the #GtkWidget::event and possibly an
- * event-specific signal on a widget. gtk_propagate_event() is a bit
- * higher-level, and gtk_main_do_event() is the highest level.
- *
- * All that said, you most likely don't want to use any of these
- * functions; synthesizing events is rarely needed. There are almost
- * certainly better ways to achieve your goals. For example, use
- * gdk_window_invalidate_rect() or gtk_widget_queue_draw() instead
- * of making up expose events.
- */
-void
-gtk_propagate_event (GtkWidget *widget,
- GdkEvent *event)
+static gboolean
+propagate_event_up (GtkWidget *widget,
+ GdkEvent *event,
+ GtkWidget *topmost)
{
- gint handled_event;
+ gboolean handled_event = FALSE;
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (event != NULL);
+ /* Propagate event up the widget tree so that
+ * parents can see the button and motion
+ * events of the children.
+ */
+ while (TRUE)
+ {
+ GtkWidget *tmp;
+
+ g_object_ref (widget);
- handled_event = FALSE;
+ /* 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 = event->type != GDK_SCROLL;
+ else
+ handled_event = gtk_widget_event (widget, event);
- g_object_ref (widget);
+ tmp = gtk_widget_get_parent (widget);
+ g_object_unref (widget);
+
+ if (widget == topmost)
+ break;
+
+ widget = tmp;
+
+ if (handled_event || !widget)
+ break;
+ }
- if ((event->type == GDK_KEY_PRESS) ||
- (event->type == GDK_KEY_RELEASE))
+ return handled_event;
+}
+
+static gboolean
+propagate_event_down (GtkWidget *widget,
+ GdkEvent *event,
+ GtkWidget *topmost)
+{
+ gint handled_event = FALSE;
+ GList *widgets = NULL;
+ GList *l;
+
+ widgets = g_list_prepend (widgets, g_object_ref (widget));
+ while (widget && widget != topmost)
+ {
+ widget = gtk_widget_get_parent (widget);
+ if (!widget)
+ break;
+
+ widgets = g_list_prepend (widgets, g_object_ref (widget));
+
+ if (widget == topmost)
+ break;
+ }
+
+ for (l = widgets; l && !handled_event; l = g_list_next (l))
+ {
+ widget = (GtkWidget *)l->data;
+
+ if (!gtk_widget_is_sensitive (widget))
+ {
+ /* stop propagating on SCROLL, but don't handle the event, so it
+ * can propagate up again and reach its handling widget
+ */
+ if (event->type == GDK_SCROLL)
+ break;
+ else
+ handled_event = TRUE;
+ }
+ else
+ handled_event = _gtk_widget_captured_event (widget, event);
+ }
+ g_list_free_full (widgets, (GDestroyNotify)g_object_unref);
+
+ return handled_event;
+}
+
+static gboolean
+propagate_event (GtkWidget *widget,
+ GdkEvent *event,
+ gboolean captured,
+ GtkWidget *topmost)
+{
+ gboolean handled_event = FALSE;
+ gboolean (* propagate_func) (GtkWidget *widget, GdkEvent *event);
+
+ propagate_func = captured ? _gtk_widget_captured_event : gtk_widget_event;
+
+ if (event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE)
{
/* Only send key events within Window widgets to the Window
* The Window widget will in turn pass the
window = gtk_widget_get_toplevel (widget);
if (GTK_IS_WINDOW (window))
{
+ g_object_ref (widget);
/* If there is a grab within the window, give the grab widget
* a first crack at the key event
*/
if (widget != window && gtk_widget_has_grab (widget))
- handled_event = gtk_widget_event (widget, event);
+ handled_event = propagate_func (widget, event);
if (!handled_event)
{
if (GTK_IS_WINDOW (window))
{
if (gtk_widget_is_sensitive (window))
- gtk_widget_event (window, event);
+ handled_event = propagate_func (window, event);
}
}
- handled_event = TRUE; /* don't send to widget */
+ g_object_unref (widget);
+ return handled_event;
}
}
- /* Other events get propagated up the widget tree
- * so that parents can see the button and motion
- * events of the children.
- */
- if (!handled_event)
- {
- while (TRUE)
- {
- GtkWidget *tmp;
-
- /* 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 = event->type != GDK_SCROLL;
- else
- handled_event = gtk_widget_event (widget, event);
+ /* Other events get propagated up/down the widget tree */
+ return captured ?
+ propagate_event_down (widget, event, topmost) :
+ propagate_event_up (widget, event, topmost);
+}
- tmp = gtk_widget_get_parent (widget);
- g_object_unref (widget);
+/**
+ * gtk_propagate_event:
+ * @widget: a #GtkWidget
+ * @event: an event
+ *
+ * Sends an event to a widget, propagating the event to parent widgets
+ * if the event remains unhandled.
+ *
+ * Events received by GTK+ from GDK normally begin in gtk_main_do_event().
+ * Depending on the type of event, existence of modal dialogs, grabs, etc.,
+ * the event may be propagated; if so, this function is used.
+ *
+ * gtk_propagate_event() calls gtk_widget_event() on each widget it
+ * decides to send the event to. So gtk_widget_event() is the lowest-level
+ * function; it simply emits the #GtkWidget::event and possibly an
+ * event-specific signal on a widget. gtk_propagate_event() is a bit
+ * higher-level, and gtk_main_do_event() is the highest level.
+ *
+ * All that said, you most likely don't want to use any of these
+ * functions; synthesizing events is rarely needed. There are almost
+ * certainly better ways to achieve your goals. For example, use
+ * gdk_window_invalidate_rect() or gtk_widget_queue_draw() instead
+ * of making up expose events.
+ */
+void
+gtk_propagate_event (GtkWidget *widget,
+ GdkEvent *event)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (event != NULL);
- widget = tmp;
+ propagate_event (widget, event, FALSE, NULL);
+}
- if (!handled_event && widget)
- g_object_ref (widget);
- else
- break;
- }
- }
- else
- g_object_unref (widget);
+gboolean
+_gtk_propagate_captured_event (GtkWidget *widget,
+ GdkEvent *event,
+ GtkWidget *topmost)
+{
+ return propagate_event (widget, event, TRUE, topmost);
}