<commit_before>/* GDK - The GIMP Drawing Kit
 * Copyright (C) 2009 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * 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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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.
 */

#include "config.h"

#include "gdkeventsource.h"

#include "gdkinternals.h"
#include "gdkwindow-x11.h"
#include "gdkprivate-x11.h"


static gboolean gdk_event_source_prepare  (GSource     *source,
                                           gint        *timeout);
static gboolean gdk_event_source_check    (GSource     *source);
static gboolean gdk_event_source_dispatch (GSource     *source,
                                           GSourceFunc  callback,
                                           gpointer     user_data);
static void     gdk_event_source_finalize (GSource     *source);

#define HAS_FOCUS(toplevel)                           \
  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)

struct _GdkEventSource
{
  GSource source;

  GdkDisplay *display;
  GPollFD event_poll_fd;
  GList *translators;
};

static GSourceFuncs event_funcs = {
  gdk_event_source_prepare,
  gdk_event_source_check,
  gdk_event_source_dispatch,
  gdk_event_source_finalize
};

static GList *event_sources = NULL;

static gint
gdk_event_apply_filters (XEvent    *xevent,
			 GdkEvent  *event,
			 GdkWindow *window)
{
  GList *tmp_list;
  GdkFilterReturn result;

  if (window == NULL)
    tmp_list = _gdk_default_filters;
  else
    tmp_list = window->filters;

  while (tmp_list)
    {
      GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
      GList *node;

      if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
        {
          tmp_list = tmp_list->next;
          continue;
        }

      filter->ref_count++;
      result = filter->function (xevent, event, filter->data);

      /* Protect against unreffing the filter mutating the list */
      node = tmp_list->next;

      _gdk_event_filter_unref (window, filter);

      tmp_list = node;

      if (result != GDK_FILTER_CONTINUE)
        return result;
    }

  return GDK_FILTER_CONTINUE;
}

static GdkWindow *
gdk_event_source_get_filter_window (GdkEventSource *event_source,
                                    XEvent         *xevent)
{
  GdkWindow *window;

  window = gdk_x11_window_lookup_for_display (event_source->display,
                                              xevent->xany.window);

  if (window && !GDK_IS_WINDOW (window))
    window = NULL;

  return window;
}

static void
handle_focus_change (GdkEventCrossing *event)
{
  GdkToplevelX11 *toplevel;
  gboolean focus_in, had_focus;

  toplevel = _gdk_x11_window_get_toplevel (event->window);
  focus_in = (event->type == GDK_ENTER_NOTIFY);

  if (!toplevel || event->detail == GDK_NOTIFY_INFERIOR)
    return;

  toplevel->has_pointer = focus_in;

  if (!event->focus || toplevel->has_focus_window)
    return;

  had_focus = HAS_FOCUS (toplevel);
  toplevel->has_pointer_focus = focus_in;

  if (HAS_FOCUS (toplevel) != had_focus)
    {
      GdkEvent *focus_event;

      focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
      focus_event->focus_change.window = g_object_ref (event->window);
      focus_event->focus_change.send_event = FALSE;
      focus_event->focus_change.in = focus_in;
      gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));

      gdk_event_put (focus_event);
      gdk_event_free (focus_event);
    }
}

static GdkEvent *
gdk_event_source_translate_event (GdkEventSource *event_source,
                                  XEvent         *xevent)
{
  GdkEvent *event = gdk_event_new (GDK_NOTHING);
  GList *list = event_source->translators;
  GdkFilterReturn result;
  GdkWindow *filter_window;

  /* Run default filters */
  if (_gdk_default_filters)
    {
      /* Apply global filters */

      result = gdk_event_apply_filters (xevent, event, NULL);

      if (result == GDK_FILTER_REMOVE)
        {
          gdk_event_free (event);
          return NULL;
        }
      else if (result == GDK_FILTER_TRANSLATE)
        return event;
    }

  filter_window = gdk_event_source_get_filter_window (event_source, xevent);

  if (filter_window)
    {
      /* Apply per-window filters */
      GdkFilterReturn result;

      event->any.window = g_object_ref (filter_window);

      if (filter_window->filters)
	{
	  result = gdk_event_apply_filters (xevent, event,
					    filter_window);

          if (result == GDK_FILTER_REMOVE)
            {
              gdk_event_free (event);
              return NULL;
            }
          else if (result == GDK_FILTER_TRANSLATE)
            return event;<commit_msg>x11: Fill in event->any.window before calling filter functions<commit_after>/* GDK - The GIMP Drawing Kit
 * Copyright (C) 2009 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * 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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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.
 */

#include "config.h"

#include "gdkeventsource.h"

#include "gdkinternals.h"
#include "gdkwindow-x11.h"
#include "gdkprivate-x11.h"


static gboolean gdk_event_source_prepare  (GSource     *source,
                                           gint        *timeout);
static gboolean gdk_event_source_check    (GSource     *source);
static gboolean gdk_event_source_dispatch (GSource     *source,
                                           GSourceFunc  callback,
                                           gpointer     user_data);
static void     gdk_event_source_finalize (GSource     *source);

#define HAS_FOCUS(toplevel)                           \
  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)

struct _GdkEventSource
{
  GSource source;

  GdkDisplay *display;
  GPollFD event_poll_fd;
  GList *translators;
};

static GSourceFuncs event_funcs = {
  gdk_event_source_prepare,
  gdk_event_source_check,
  gdk_event_source_dispatch,
  gdk_event_source_finalize
};

static GList *event_sources = NULL;

static gint
gdk_event_apply_filters (XEvent    *xevent,
			 GdkEvent  *event,
			 GdkWindow *window)
{
  GList *tmp_list;
  GdkFilterReturn result;

  if (window == NULL)
    tmp_list = _gdk_default_filters;
  else
    tmp_list = window->filters;

  while (tmp_list)
    {
      GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
      GList *node;

      if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
        {
          tmp_list = tmp_list->next;
          continue;
        }

      filter->ref_count++;
      result = filter->function (xevent, event, filter->data);

      /* Protect against unreffing the filter mutating the list */
      node = tmp_list->next;

      _gdk_event_filter_unref (window, filter);

      tmp_list = node;

      if (result != GDK_FILTER_CONTINUE)
        return result;
    }

  return GDK_FILTER_CONTINUE;
}

static GdkWindow *
gdk_event_source_get_filter_window (GdkEventSource *event_source,
                                    XEvent         *xevent)
{
  GdkWindow *window;

  window = gdk_x11_window_lookup_for_display (event_source->display,
                                              xevent->xany.window);

  if (window && !GDK_IS_WINDOW (window))
    window = NULL;

  return window;
}

static void
handle_focus_change (GdkEventCrossing *event)
{
  GdkToplevelX11 *toplevel;
  gboolean focus_in, had_focus;

  toplevel = _gdk_x11_window_get_toplevel (event->window);
  focus_in = (event->type == GDK_ENTER_NOTIFY);

  if (!toplevel || event->detail == GDK_NOTIFY_INFERIOR)
    return;

  toplevel->has_pointer = focus_in;

  if (!event->focus || toplevel->has_focus_window)
    return;

  had_focus = HAS_FOCUS (toplevel);
  toplevel->has_pointer_focus = focus_in;

  if (HAS_FOCUS (toplevel) != had_focus)
    {
      GdkEvent *focus_event;

      focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
      focus_event->focus_change.window = g_object_ref (event->window);
      focus_event->focus_change.send_event = FALSE;
      focus_event->focus_change.in = focus_in;
      gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));

      gdk_event_put (focus_event);
      gdk_event_free (focus_event);
    }
}

static GdkEvent *
gdk_event_source_translate_event (GdkEventSource *event_source,
                                  XEvent         *xevent)
{
  GdkEvent *event = gdk_event_new (GDK_NOTHING);
  GList *list = event_source->translators;
  GdkFilterReturn result;
  GdkWindow *filter_window;

  filter_window = gdk_event_source_get_filter_window (event_source, xevent);
  if (filter_window)
    event->any.window = g_object_ref (filter_window);

  /* Run default filters */
  if (_gdk_default_filters)
    {
      /* Apply global filters */

      result = gdk_event_apply_filters (xevent, event, NULL);

      if (result == GDK_FILTER_REMOVE)
        {
          gdk_event_free (event);
          return NULL;
        }
      else if (result == GDK_FILTER_TRANSLATE)
        return event;
    }

  if (filter_window)
    {
      /* Apply per-window filters */
      GdkFilterReturn result;

      if (filter_window->filters)
	{
	  result = gdk_event_apply_filters (xevent, event,
					    filter_window);

          if (result == GDK_FILTER_REMOVE)
            {
              gdk_event_free (event);
              return NULL;
            }
          else if (result == GDK_FILTER_TRANSLATE)
            return event;
{'fraction_non_alphanumeric': 0.08597670675125461, 'fraction_numerical': 0.005870656187860998, 'mean_word_length': 2.702067998597967, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3185665', 'n_tokens_mistral': 3450, 'n_tokens_neox': 3310, 'n_words': 824}