/* GDK - The GIMP Drawing Kit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * 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.
 */

/*
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 * file for a list of people on the GTK+ Team.
 */

/*
 * GTK+ DirectFB backend
 * Copyright (C) 2001-2002  convergence integrated media GmbH
 * Copyright (C) 2002-2004  convergence GmbH
 * Written by Denis Oliver Kropp <dok@convergence.de> and
 *            Sven Neumann <sven@convergence.de>
 */

#include "config.h"
#include "gdk.h"
#include "gdkdirectfb.h"
#include "gdkprivate-directfb.h"

#include "gdkinternals.h"

#include "gdkkeysyms.h"

#include "gdkinput-directfb.h"
#include <string.h>

#ifndef __GDK_X_H__
#define __GDK_X_H__
gboolean gdk_net_wm_supports (GdkAtom property);
#endif

#include "gdkalias.h"

#define EventBuffer _gdk_display->buffer
#define DirectFB _gdk_display->directfb




#include "gdkaliasdef.c"

/*********************************************
 * Functions for maintaining the event queue *
 *********************************************/

static GdkEvent * gdk_event_translate  (DFBWindowEvent  *dfbevent,
                                        GdkWindow       *window);

/*
 * Private variable declarations
 */
static GList *client_filters;  /* Filters for client messages */


static void
fixup_event (GdkEvent *event)
{
  if (event->any.window)
    g_object_ref (event->any.window);
  if (((event->any.type == GDK_ENTER_NOTIFY) ||
       (event->any.type == GDK_LEAVE_NOTIFY)) &&
      (event->crossing.subwindow != NULL))
    g_object_ref (event->crossing.subwindow);
  event->any.send_event = FALSE;
}

static GdkFilterReturn
apply_filters (GdkWindow      *window,
               DFBWindowEvent *dfbevent,
               GList          *filters)
{
  GdkFilterReturn result = GDK_FILTER_CONTINUE;
  GdkEvent *event;
  GList *node;
  GList *tmp_list;

  event = gdk_event_new (GDK_NOTHING);
  if (window != NULL)
    event->any.window = g_object_ref (window);
  ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;

  /* I think GdkFilterFunc semantics require the passed-in event
   * to already be in the queue. The filter func can generate
   * more events and append them after it if it likes.
   */
  node = _gdk_event_queue_append ((GdkDisplay*)_gdk_display, event);
  
  tmp_list = filters;
  while (tmp_list)
    {
      GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data;
      
      tmp_list = tmp_list->next;
      result = filter->function (dfbevent, event, filter->data);
      if (result != GDK_FILTER_CONTINUE)
        break;
    }

  if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE)
    {
      _gdk_event_queue_remove_link ((GdkDisplay*)_gdk_display, node);
      g_list_free_1 (node);
      gdk_event_free (event);
    }
  else /* GDK_FILTER_TRANSLATE */
    {
      ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
      fixup_event (event);
    }
  return result;
}

static void
dfb_events_process_window_event (DFBWindowEvent *event)
{
  GdkWindow *window;

  /*
   * Apply global filters
   *
   * If result is GDK_FILTER_CONTINUE, we continue as if nothing
   * happened. If it is GDK_FILTER_REMOVE or GDK_FILTER_TRANSLATE,
   * we return TRUE and won't dispatch the event.
   */
  if (_gdk_default_filters)
    {
      switch (apply_filters (NULL, event, _gdk_default_filters))
        {
        case GDK_FILTER_REMOVE:
        case GDK_FILTER_TRANSLATE:
          return;

        default:
          break;
        }
    }

  window = gdk_directfb_window_id_table_lookup (event->window_id);
  if (!window)
    return;

  gdk_event_translate (event, window);
}

static gboolean
gdk_event_send_client_message_by_window (GdkEvent *event,
                                         GdkWindow *window)
{
  DFBUserEvent evt;

  g_return_val_if_fail(event != NULL, FALSE);
  g_return_val_if_fail(GDK_IS_WINDOW(window), FALSE);

  evt.clazz = DFEC_USER;
  evt.type = GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (event->client.message_type));
  evt.data = (void *) event->client.data.l[0];

  _gdk_display->buffer->PostEvent(_gdk_display->buffer, DFB_EVENT (&evt));

  return TRUE;
}

static void
dfb_events_dispatch (void)
{
  GdkDisplay *display = gdk_display_get_default ();
  GdkEvent   *event;

  GDK_THREADS_ENTER ();

  while ((event = _gdk_event_unqueue (display)) != NULL)
    {
      if (_gdk_event_func)
        (*_gdk_event_func) (event, _gdk_event_data);

      gdk_event_free (event);
    }

  GDK_THREADS_LEAVE ();
}

static gboolean
dfb_events_io_func (GIOChannel   *channel,
                    GIOCondition  condition,
                    gpointer      data)
{
  gsize      i;
  gsize      read;
  GIOStatus  result;
  DFBEvent   buf[23];
  DFBEvent  *event;

  result = g_io_channel_read_chars (channel,
                                    (gchar *) buf, sizeof (buf), &read, NULL);

  if (result == G_IO_STATUS_ERROR)
    {
      g_warning ("%s: GIOError occured", G_STRFUNC);
      return TRUE;
    }

  read /= sizeof (DFBEvent);

  for (i = 0, event = buf; i < read; i++, event++)
    {
      switch (event->clazz)
        {
        case DFEC_WINDOW:
          /* TODO workaround to prevent two DWET_ENTER in a row from being delivered */
          if (event->window.type == DWET_ENTER ) {
            if ( i>0 && buf[i-1].window.type != DWET_ENTER )
              dfb_events_process_window_event (&event->window);
          }
          else
            dfb_events_process_window_event (&event->window);
          break;

        case DFEC_USER:
          {
            GList *list;

            GDK_NOTE (EVENTS, g_print (" client_message"));

            for (list = client_filters; list; list = list->next)
              {
                GdkClientFilter *filter     = list->data;
                DFBUserEvent    *user_event = (DFBUserEvent *) event;
                GdkAtom          type;

                type = GDK_POINTER_TO_ATOM (GUINT_TO_POINTER (user_event->type));

                if (filter->type == type)
                  {
                    if (filter->function (user_event,
                                          NULL,
                                          filter->data) != GDK_FILTER_CONTINUE)
                      break;
                  }
              }
          }
          break;

        default:
          break;
        }
    }

  EventBuffer->Reset (EventBuffer);

  dfb_events_dispatch ();

  return TRUE;
}

void
_gdk_events_init (void)
{
  GIOChannel *channel;
  GSource    *source;
  DFBResult   ret;
  gint        fd;

  ret = DirectFB->CreateEventBuffer (DirectFB, &EventBuffer);
  if (ret)
    {
      DirectFBError ("_gdk_events_init: "
                     "IDirectFB::CreateEventBuffer() failed", ret);
      return;
    }

  ret = EventBuffer->CreateFileDescriptor (EventBuffer, &fd);
  if (ret)
    {
      DirectFBError ("_gdk_events_init: "
                     "IDirectFBEventBuffer::CreateFileDescriptor() failed",
                     ret);
      return;
    }

  channel = g_io_channel_unix_new (fd);

  g_io_channel_set_encoding (channel, NULL, NULL);
  g_io_channel_set_buffered (channel, FALSE);

  source = g_io_create_watch (channel, G_IO_IN);

  g_source_set_priority (source, G_PRIORITY_DEFAULT);
  g_source_set_can_recurse (source, TRUE);
  g_source_set_callback (source, (GSourceFunc) dfb_events_io_func, NULL, NULL);

  g_source_attach (source, NULL);
  g_source_unref (source);
}

gboolean
gdk_events_pending (void)
{
  GdkDisplay *display = gdk_display_get_default ();

  return _gdk_event_queue_find_first (display) ? TRUE : FALSE;
}

GdkEvent *
gdk_event_get_graphics_expose (GdkWindow *window)
{
  GdkDisplay *display;
  GList      *list;

  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

  display = gdk_drawable_get_display (GDK_DRAWABLE (window));

  for (list = _gdk_event_queue_find_first (display); list; list = list->next)
    {
      GdkEvent *event = list->data;
      if (event->type == GDK_EXPOSE && event->expose.window == window)
        break;
    }

  if (list)
    {
      GdkEvent *retval = list->data;

      _gdk_event_queue_remove_link (display, list);
      g_list_free_1 (list);

      return retval;
    }

  return NULL;
}

void
_gdk_events_queue (GdkDisplay *display)
{
}

void
gdk_flush (void)
{
gdk_display_flush ( GDK_DISPLAY_OBJECT(_gdk_display));
}

/* Sends a ClientMessage to all toplevel client windows */
gboolean
gdk_event_send_client_message_for_display (GdkDisplay *display,
                                           GdkEvent   *event,
                                           guint32     xid)
{
  GdkWindow *win = NULL;
  gboolean ret = TRUE;

  g_return_val_if_fail(event != NULL, FALSE);

  win = gdk_window_lookup_for_display (display, (GdkNativeWindow) xid);

  g_return_val_if_fail(win != NULL, FALSE);

  if ((GDK_WINDOW_OBJECT(win)->window_type != GDK_WINDOW_CHILD) &&
      (g_object_get_data (G_OBJECT (win), "gdk-window-child-handler")))
    {
      /* Managed window, check children */
      GList *ltmp = NULL;
      for (ltmp = GDK_WINDOW_OBJECT(win)->children; ltmp; ltmp = ltmp->next)
       {
         ret &= gdk_event_send_client_message_by_window (event,
                                                         GDK_WINDOW(ltmp->data));
       }
    }
  else
    {
      ret &= gdk_event_send_client_message_by_window (event, win);
    }

  return ret;
}

/*****/

guint32
gdk_directfb_get_time (void)
{
  GTimeVal tv;

  g_get_current_time (&tv);

  return (guint32) tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

void
gdk_directfb_event_windows_add (GdkWindow *window)
{
  GdkWindowImplDirectFB *impl;

  g_return_if_fail (GDK_IS_WINDOW (window));

  impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);

  if (!impl->window)
    return;

  if (EventBuffer)
    impl->window->AttachEventBuffer (impl->window, EventBuffer);
  else
    impl->window->CreateEventBuffer (impl->window, &EventBuffer);
}

void
gdk_directfb_event_windows_remove (GdkWindow *window)
{
  GdkWindowImplDirectFB *impl;

  g_return_if_fail (GDK_IS_WINDOW (window));

  impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);

  if (!impl->window)
    return;

  if (EventBuffer)
    impl->window->DetachEventBuffer (impl->window, EventBuffer);
/* FIXME: should we warn if (! EventBuffer) ? */
}

GdkWindow *
gdk_directfb_child_at (GdkWindow *window,
                       gint      *winx,
                       gint      *winy)
{
  GdkWindowObject *private;
  GList           *list;

  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

  private = GDK_WINDOW_OBJECT (window);
  for (list = private->children; list; list = list->next)
    {
      GdkWindowObject *win = list->data;

      if (GDK_WINDOW_IS_MAPPED (win) &&
          *winx >= win->x  &&
          *winx <  win->x + GDK_DRAWABLE_IMPL_DIRECTFB (win->impl)->width  &&
          *winy >= win->y  &&
          *winy <  win->y + GDK_DRAWABLE_IMPL_DIRECTFB (win->impl)->height)
        {
          *winx -= win->x;
          *winy -= win->y;

          return gdk_directfb_child_at (GDK_WINDOW (win), winx, winy );
        }
    }

  return window;
}

static GdkEvent *
gdk_event_translate (DFBWindowEvent *dfbevent,
                     GdkWindow      *window)
{
  GdkWindowObject *private;
  GdkDisplay      *display;
  GdkEvent        *event    = NULL;

  g_return_val_if_fail (dfbevent != NULL, NULL);
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

  private = GDK_WINDOW_OBJECT (window);

  g_object_ref (G_OBJECT (window));

  /*
   * Apply per-window filters
   *
   * If result is GDK_FILTER_CONTINUE, we continue as if nothing
   * happened. If it is GDK_FILTER_REMOVE or GDK_FILTER_TRANSLATE,
   * we return TRUE and won't dispatch the event.
   */
  if (private->filters)
    {
      switch (apply_filters (window, dfbevent, private->filters))
        {
        case GDK_FILTER_REMOVE:
        case GDK_FILTER_TRANSLATE:
          g_object_unref (G_OBJECT (window));
          return NULL;

        default:
          break;
        }
    }

  display = gdk_drawable_get_display (GDK_DRAWABLE (window));

  switch (dfbevent->type)
    {
    case DWET_BUTTONDOWN:
    case DWET_BUTTONUP:
      {
        static gboolean  click_grab = FALSE;
        GdkWindow       *child;
        gint             wx, wy;
        guint            mask;
        guint            button;

        _gdk_directfb_mouse_x = wx = dfbevent->cx;
        _gdk_directfb_mouse_y = wy = dfbevent->cy;

        switch (dfbevent->button)
          {
          case DIBI_LEFT:
            button = 1;
            mask   = GDK_BUTTON1_MASK;
            break;
          case DIBI_MIDDLE:
            button = 2;
            mask   = GDK_BUTTON2_MASK;
            break;
          case DIBI_RIGHT:
            button = 3;
            mask   = GDK_BUTTON3_MASK;
            break;
          default:
            button = dfbevent->button + 1;
            mask   = 0;
            break;
          }

        child = gdk_directfb_child_at (_gdk_parent_root, &wx, &wy);

        if (_gdk_directfb_pointer_grab_window &&
            (_gdk_directfb_pointer_grab_events & (dfbevent->type ==
                                                  DWET_BUTTONDOWN ?
                                                  GDK_BUTTON_PRESS_MASK :
                                                  GDK_BUTTON_RELEASE_MASK)) &&
            (_gdk_directfb_pointer_grab_owner_events == FALSE ||
             child == _gdk_parent_root) )
          {
            GdkDrawableImplDirectFB *impl;

            child = _gdk_directfb_pointer_grab_window;
            impl  = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (child)->impl);

            dfbevent->x = dfbevent->cx - impl->abs_x;
            dfbevent->y = dfbevent->cy - impl->abs_y;
          }
        else if (!_gdk_directfb_pointer_grab_window ||
                 (_gdk_directfb_pointer_grab_owner_events == TRUE))
          {
            dfbevent->x = wx;
            dfbevent->y = wy;
          }
        else
          {
            child = NULL;
          }

        if (dfbevent->type == DWET_BUTTONDOWN)
          _gdk_directfb_modifiers |= mask;
        else
          _gdk_directfb_modifiers &= ~mask;

        if (child)
          {
            event =
              gdk_directfb_event_make (child,
                                       dfbevent->type == DWET_BUTTONDOWN ?
                                       GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);

            event->button.x_root = _gdk_directfb_mouse_x;
            event->button.y_root = _gdk_directfb_mouse_y;

            event->button.x = dfbevent->x;
            event->button.y = dfbevent->y;

            event->button.state  = _gdk_directfb_modifiers;
            event->button.button = button;
            event->button.device = display->core_pointer;

            GDK_NOTE (EVENTS,
                      g_message ("button: %d at %d,%d %s with state 0x%08x",
                                 event->button.button,
                                 (int)event->button.x, (int)event->button.y,
                                 dfbevent->type == DWET_BUTTONDOWN ?
                                 "pressed" : "released",
                                 _gdk_directfb_modifiers));

            if (dfbevent->type == DWET_BUTTONDOWN)
              _gdk_event_button_generate (display, event);
          }

        /* Handle implicit button grabs: */
        if (dfbevent->type == DWET_BUTTONDOWN  &&  !click_grab  &&  child)
          {
            if (gdk_directfb_pointer_grab (child, FALSE,
                                           gdk_window_get_events (child),
                                           NULL, NULL,
                                           GDK_CURRENT_TIME,
                                           TRUE) == GDK_GRAB_SUCCESS)
              click_grab = TRUE;
          }
        else if (dfbevent->type == DWET_BUTTONUP &&
                 !(_gdk_directfb_modifiers & (GDK_BUTTON1_MASK |
                                              GDK_BUTTON2_MASK |
                                              GDK_BUTTON3_MASK)) && click_grab)
          {
            gdk_directfb_pointer_ungrab (GDK_CURRENT_TIME, TRUE);
            click_grab = FALSE;
          }
      }
      break;

    case DWET_MOTION:
      {
        GdkWindow *event_win=NULL;
        GdkWindow *child;

        _gdk_directfb_mouse_x = dfbevent->cx;
        _gdk_directfb_mouse_y = dfbevent->cy;

	//child = gdk_directfb_child_at (window, &dfbevent->x, &dfbevent->y);
    /* Go all the way to root to catch popup menus */
    int wx=_gdk_directfb_mouse_x;
    int wy=_gdk_directfb_mouse_y;
	child = gdk_directfb_child_at (_gdk_parent_root, &wx, &wy);

    /* first let's see if any cossing event has to be send */
    gdk_directfb_window_send_crossing_events (NULL, child, GDK_CROSSING_NORMAL);

    /* then dispatch the motion event to the window the cursor it's inside */
	event_win = gdk_directfb_pointer_event_window (child, GDK_MOTION_NOTIFY);


	if (event_win)
	  {

	    if (event_win == _gdk_directfb_pointer_grab_window) {
		GdkDrawableImplDirectFB *impl;

		child = _gdk_directfb_pointer_grab_window;
		impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (child)->impl);

		dfbevent->x = _gdk_directfb_mouse_x - impl->abs_x;
		dfbevent->y = _gdk_directfb_mouse_y - impl->abs_y;
	      }

	    event = gdk_directfb_event_make (child, GDK_MOTION_NOTIFY);

	    event->motion.x_root = _gdk_directfb_mouse_x;
	    event->motion.y_root = _gdk_directfb_mouse_y;

	    //event->motion.x = dfbevent->x;
	    //event->motion.y = dfbevent->y;
	    event->motion.x = wx;
	    event->motion.y = wy;

	    event->motion.state   = _gdk_directfb_modifiers;
	    event->motion.is_hint = FALSE;
	    event->motion.device  = display->core_pointer;

	    if (GDK_WINDOW_OBJECT (event_win)->event_mask &
		GDK_POINTER_MOTION_HINT_MASK)
	      {
		while (EventBuffer->PeekEvent (EventBuffer,
					       DFB_EVENT (dfbevent)) == DFB_OK
		       && dfbevent->type == DWET_MOTION)
		  {
		    EventBuffer->GetEvent (EventBuffer, DFB_EVENT (dfbevent));
		    event->motion.is_hint = TRUE;
		  }
	      }
	  }
          /* make sure crossing events go to the event window found */
/*        GdkWindow *ev_win = ( event_win == NULL ) ? gdk_window_at_pointer (NULL,NULL) :event_win;
	     gdk_directfb_window_send_crossing_events (NULL,ev_win,GDK_CROSSING_NORMAL);
*/
      }
      break;

    case DWET_GOTFOCUS:
      gdk_directfb_change_focus (window);

      break;

    case DWET_LOSTFOCUS:
      gdk_directfb_change_focus (_gdk_parent_root);

      break;

    case DWET_POSITION:
      {
        GdkWindow *event_win;

        private->x = dfbevent->x;
        private->y = dfbevent->y;

        event_win = gdk_directfb_other_event_window (window, GDK_CONFIGURE);

        if (event_win)
          {
            event = gdk_directfb_event_make (event_win, GDK_CONFIGURE);
            event->configure.x = dfbevent->x;
            event->configure.y = dfbevent->y;
            event->configure.width =
              GDK_DRAWABLE_IMPL_DIRECTFB (private->impl)->width;
            event->configure.height =
              GDK_DRAWABLE_IMPL_DIRECTFB (private->impl)->height;
          }

        _gdk_directfb_calc_abs (window);
      }
      break;

    case DWET_POSITION_SIZE:
      private->x = dfbevent->x;
      private->y = dfbevent->y;
      /* fallthru */

    case DWET_SIZE:
      {
        GdkDrawableImplDirectFB *impl;
        GdkWindow               *event_win;
        GList                   *list;

        impl = GDK_DRAWABLE_IMPL_DIRECTFB (private->impl);

        event_win = gdk_directfb_other_event_window (window, GDK_CONFIGURE);

        if (event_win)
          {
            event = gdk_directfb_event_make (event_win, GDK_CONFIGURE);
            event->configure.x      = private->x;
            event->configure.y      = private->y;
            event->configure.width  = dfbevent->w;
            event->configure.height = dfbevent->h;
          }

        impl->width  = dfbevent->w;
        impl->height = dfbevent->h;

        for (list = private->children; list; list = list->next)
          {
            GdkWindowObject         *win;
            GdkDrawableImplDirectFB *impl;

            win  = GDK_WINDOW_OBJECT (list->data);
            impl = GDK_DRAWABLE_IMPL_DIRECTFB (win->impl);

            _gdk_directfb_move_resize_child (GDK_WINDOW (win),
                                             win->x, win->y,
                                             impl->width, impl->height);
          }

        _gdk_directfb_calc_abs (window);

        gdk_window_clear (window);
        gdk_window_invalidate_rect (window, NULL, TRUE);
      }
      break;

    case DWET_KEYDOWN:
    case DWET_KEYUP:
      {

        GdkEventType type = (dfbevent->type == DWET_KEYUP ?
                             GDK_KEY_RELEASE : GDK_KEY_PRESS);
        GdkWindow *event_win =
          gdk_directfb_keyboard_event_window (gdk_directfb_window_find_focus (),
                                              type);
        if (event_win)
          {
            event = gdk_directfb_event_make (event_win, type);
            gdk_directfb_translate_key_event (dfbevent, &event->key);
          }
      }
      break;

    case DWET_LEAVE:
      _gdk_directfb_mouse_x = dfbevent->cx;
      _gdk_directfb_mouse_y = dfbevent->cy;

      gdk_directfb_window_send_crossing_events (NULL, _gdk_parent_root,
                                                GDK_CROSSING_NORMAL);

      if (gdk_directfb_apply_focus_opacity)
        {
          if (GDK_WINDOW_IS_MAPPED (window))
            GDK_WINDOW_IMPL_DIRECTFB (private->impl)->window->SetOpacity
              (GDK_WINDOW_IMPL_DIRECTFB (private->impl)->window,
               (GDK_WINDOW_IMPL_DIRECTFB (private->impl)->opacity >> 1) +
               (GDK_WINDOW_IMPL_DIRECTFB (private->impl)->opacity >> 2));
        }
      break;

    case DWET_ENTER:
      {
        GdkWindow *child;

        _gdk_directfb_mouse_x = dfbevent->cx;
        _gdk_directfb_mouse_y = dfbevent->cy;

        child = gdk_directfb_child_at (window, &dfbevent->x, &dfbevent->y);

        /* this makes sure pointer is set correctly when it previously left
         * a window being not standard shaped
         */
        gdk_window_set_cursor (window, NULL);
        gdk_directfb_window_send_crossing_events (NULL, child,
                                                  GDK_CROSSING_NORMAL);

        if (gdk_directfb_apply_focus_opacity)
          {
            GDK_WINDOW_IMPL_DIRECTFB (private->impl)->window->SetOpacity
              (GDK_WINDOW_IMPL_DIRECTFB (private->impl)->window,
               GDK_WINDOW_IMPL_DIRECTFB (private->impl)->opacity);
          }
      }
      break;

    case DWET_CLOSE:
      {
 
        GdkWindow *event_win;

        event_win = gdk_directfb_other_event_window (window, GDK_DELETE);

        if (event_win)
          event = gdk_directfb_event_make (event_win, GDK_DELETE);
      }
      break;

    case DWET_DESTROYED:
      {
        GdkWindow *event_win;

        event_win = gdk_directfb_other_event_window (window, GDK_DESTROY);

        if (event_win)
          event = gdk_directfb_event_make (event_win, GDK_DESTROY);

	gdk_window_destroy_notify (window);
      }
      break;

    case DWET_WHEEL:
      {
        GdkWindow *event_win;

        _gdk_directfb_mouse_x = dfbevent->cx;
        _gdk_directfb_mouse_y = dfbevent->cy;

        if (_gdk_directfb_pointer_grab_window)
          {
            GdkDrawableImplDirectFB *impl;

            event_win = _gdk_directfb_pointer_grab_window;
            impl =
              GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (event_win)->impl);

            dfbevent->x = dfbevent->cx - impl->abs_x;
            dfbevent->y = dfbevent->cy - impl->abs_y;
          }
        else
          {
            event_win = gdk_directfb_child_at (window,
                                               &dfbevent->x, &dfbevent->y);
          }

        if (event_win)
          {
            event = gdk_directfb_event_make (event_win, GDK_SCROLL);

            event->scroll.direction = (dfbevent->step < 0 ?
                                       GDK_SCROLL_DOWN : GDK_SCROLL_UP);

            event->scroll.x_root = _gdk_directfb_mouse_x;
            event->scroll.y_root = _gdk_directfb_mouse_y;
            event->scroll.x      = dfbevent->x;
            event->scroll.y      = dfbevent->y;
            event->scroll.state  = _gdk_directfb_modifiers;
            event->scroll.device = display->core_pointer;
          }
      }
      break;

    default:
      g_message ("unhandled DirectFB windowing event 0x%08x", dfbevent->type);
    }

  g_object_unref (G_OBJECT (window));

  return event;
}

gboolean
gdk_screen_get_setting (GdkScreen   *screen,
                        const gchar *name,
                        GValue      *value)
{
  return FALSE;
}

void
gdk_display_add_client_message_filter (GdkDisplay   *display,
                                       GdkAtom       message_type,
                                       GdkFilterFunc func,
                                       gpointer      data)
{
  /* XXX: display should be used */
  GdkClientFilter *filter = g_new (GdkClientFilter, 1);

  filter->type = message_type;
  filter->function = func;
  filter->data = data;
  client_filters = g_list_append (client_filters, filter);
}


void
gdk_add_client_message_filter (GdkAtom       message_type,
                               GdkFilterFunc func,
                               gpointer      data)
{
  gdk_display_add_client_message_filter (gdk_display_get_default (),
                                         message_type, func, data);
}

void
gdk_screen_broadcast_client_message (GdkScreen *screen,
				     GdkEvent  *sev)
{
  GdkWindow *root_window;
  GdkWindowObject *private;
  GList *top_level = NULL;

  g_return_if_fail (GDK_IS_SCREEN (screen));
  g_return_if_fail(sev != NULL);

  root_window = gdk_screen_get_root_window (screen);

  g_return_if_fail(GDK_IS_WINDOW(root_window));

  private = GDK_WINDOW_OBJECT (root_window);

  for (top_level = private->children; top_level; top_level = top_level->next)
    {
      gdk_event_send_client_message_for_display (gdk_drawable_get_display(GDK_DRAWABLE(root_window)),
                                                sev,
                                                (guint32)(GDK_WINDOW_DFB_ID(GDK_WINDOW(top_level->data))));
   }
}


/**
 * gdk_net_wm_supports:
 * @property: a property atom.
 *
 * This function is specific to the X11 backend of GDK, and indicates
 * whether the window manager for the default screen supports a certain
 * hint from the Extended Window Manager Hints Specification. See
 * gdk_x11_screen_supports_net_wm_hint() for complete details.
 *
 * Return value: %TRUE if the window manager supports @property
 **/


gboolean
gdk_net_wm_supports (GdkAtom property)
{
   return FALSE;
}

void
_gdk_windowing_event_data_copy (const GdkEvent *src,
                                GdkEvent       *dst)
{
}

void
_gdk_windowing_event_data_free (GdkEvent *event)
{
}

#define __GDK_EVENTS_X11_C__
#include "gdkaliasdef.c"
