widget/src/gtksuperwin/gtkmozbox.c
author mark.finkle@gmail.com
Mon, 23 Apr 2007 13:27:46 -0700
changeset 738 454242ccdff6b34cf8bf80930857fe97c64f1638
parent 1 9b2a99adc05e53cd4010de512f50118594756650
permissions -rw-r--r--
bug 372069. add FUEL to trunk. r=gavin

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla.org Code.
 *
 * The Initial Developer of the Original Code is
 * Owen Taylor <otaylor@redhat.com> and Christopher Blizzard 
 * <blizzard@redhat.com>.
 * Portions created by the Initial Developer are Copyright (C) 1999
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "gtkmozbox.h"
#include <gtk/gtkmain.h>
#include <X11/Xlib.h>

static void            gtk_mozbox_class_init      (GtkMozBoxClass *klass);
static void            gtk_mozbox_init            (GtkMozBox      *mozbox);
static void            gtk_mozbox_realize         (GtkWidget      *widget);
static void            gtk_mozbox_set_focus       (GtkWindow      *window,
                                                   GtkWidget      *focus);
static gint            gtk_mozbox_key_press_event (GtkWidget   *widget,
                                                   GdkEventKey *event);
static GdkFilterReturn gtk_mozbox_filter          (GdkXEvent      *xevent,
                                                   GdkEvent       *event,
                                                   gpointer        data);
static GtkWindow *     gtk_mozbox_get_parent_gtkwindow (GtkMozBox *mozbox);

void (*parent_class_set_focus)(GtkWindow *, GtkWidget *);

GtkType
gtk_mozbox_get_type (void)
{
  static GtkType mozbox_type = 0;

  if (!mozbox_type)
    {
      static const GtkTypeInfo mozbox_info =
      {
        "GtkMozBox",
        sizeof (GtkMozBox),
        sizeof (GtkMozBoxClass),
        (GtkClassInitFunc) gtk_mozbox_class_init,
        (GtkObjectInitFunc) gtk_mozbox_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL
      };

      mozbox_type = gtk_type_unique (GTK_TYPE_WINDOW, &mozbox_info);
    }

  return mozbox_type;
}

static void
gtk_mozbox_class_init (GtkMozBoxClass *klass)
{
  GtkWidgetClass *widget_class;
  GtkWindowClass *window_class;

  widget_class = GTK_WIDGET_CLASS (klass);
  window_class = GTK_WINDOW_CLASS (klass);

  widget_class->realize         = gtk_mozbox_realize;
  widget_class->key_press_event = gtk_mozbox_key_press_event;

  /* save the parent class' set_focus method */
  parent_class_set_focus = window_class->set_focus;
  window_class->set_focus       = gtk_mozbox_set_focus;
  
}

static void
gtk_mozbox_init (GtkMozBox *mozbox)
{
  mozbox->parent_window = NULL;
  mozbox->x = 0;
  mozbox->y = 0;
}

static void
gtk_mozbox_realize (GtkWidget *widget)
{
  GdkWindowAttr attributes;
  gint attributes_mask;
  GtkMozBox *mozbox;

  g_return_if_fail (GTK_IS_MOZBOX (widget));

  mozbox = GTK_MOZBOX (widget);

  /* GtkWindow checks against premature realization here. Just
   * don't do it.
   */
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = mozbox->x;
  attributes.y = mozbox->y;
  attributes.width = widget->allocation.width;
  attributes.height = widget->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = gtk_widget_get_events (widget);
  attributes.event_mask |= GDK_EXPOSURE_MASK;
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

  widget->window = gdk_window_new (mozbox->parent_window,
				   &attributes, attributes_mask);

  /* set the back pixmap to None so that you don't end up with the gtk
     default which is BlackPixel */
  gdk_window_set_back_pixmap (widget->window, NULL, FALSE);

  gdk_window_set_user_data (widget->window, mozbox);

  widget->style = gtk_style_attach (widget->style, widget->window);
  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);

  gdk_window_add_filter (widget->window, gtk_mozbox_filter, mozbox);
}

static void
gtk_mozbox_set_focus (GtkWindow      *window,
                      GtkWidget      *focus)
{
  GtkMozBox *mozbox;
  GdkWindow *tmpWindow;
  GtkWindow *parentGtkWindow;

  g_return_if_fail(window != NULL);
  g_return_if_fail(GTK_IS_MOZBOX(window));

  mozbox = GTK_MOZBOX(window);

  parentGtkWindow = gtk_mozbox_get_parent_gtkwindow (mozbox);

  if (parentGtkWindow) {
    parent_class_set_focus(parentGtkWindow, focus);
    return;
  }

  /* as a fall back just hand it off to our parent class */
  parent_class_set_focus(window, focus);

}

static gint
gtk_mozbox_key_press_event (GtkWidget   *widget,
                            GdkEventKey *event)
{
  GtkWindow *window;
  GtkMozBox *mozbox;
  GtkWindow *parentWindow;
  gboolean   handled = FALSE;

  window = GTK_WINDOW (widget);
  mozbox = GTK_MOZBOX (widget);

  parentWindow = gtk_mozbox_get_parent_gtkwindow(mozbox);

  /* give the focus window the chance to handle the event first. */
  if (parentWindow && parentWindow->focus_widget) {
    handled = gtk_widget_event (parentWindow->focus_widget, (GdkEvent*) event);
  }

  /* pass it off to the parent widget */
  if (!handled) {
    gdk_window_unref(event->window);
    event->window = mozbox->parent_window;
    gdk_window_ref(event->window);
    gdk_event_put((GdkEvent *)event);
  }

  return TRUE;
}

static GdkFilterReturn 
gtk_mozbox_filter (GdkXEvent *xevent,
		   GdkEvent *event,
		   gpointer  data)
{
  XEvent *xev = xevent;
  GtkWidget *widget = data;

  switch (xev->xany.type)
    {
    case ConfigureNotify:
      event->configure.type = GDK_CONFIGURE;
      event->configure.window = widget->window;
      event->configure.x = 0;
      event->configure.y = 0;
      event->configure.width = xev->xconfigure.width;
      event->configure.height = xev->xconfigure.height;
      return GDK_FILTER_TRANSLATE;
    default:
      return GDK_FILTER_CONTINUE;
    }
}

static GtkWindow *
gtk_mozbox_get_parent_gtkwindow (GtkMozBox *mozbox)
{
  GdkWindow *tmpWindow;
  /* look for a parent GtkWindow in the heirarchy */
  tmpWindow = mozbox->parent_window;
  while (tmpWindow) {
    gpointer data = NULL;
    gdk_window_get_user_data(tmpWindow, &data);
    if (data && GTK_IS_WINDOW(data)) {
      return GTK_WINDOW(data);
    }
    tmpWindow = gdk_window_get_parent(tmpWindow);
  }
  return NULL;
}

GtkWidget*
gtk_mozbox_new (GdkWindow *parent_window)
{
  GtkMozBox *mozbox;

  mozbox = gtk_type_new (GTK_TYPE_MOZBOX);
  mozbox->parent_window = parent_window;

  return GTK_WIDGET (mozbox);
}

void
gtk_mozbox_set_position (GtkMozBox *mozbox,
			 gint       x,
			 gint       y)
{
  mozbox->x = x;
  mozbox->y = y;

  if (GTK_WIDGET_REALIZED (mozbox))
    gdk_window_move (GTK_WIDGET (mozbox)->window, x, y);
}