Back to index

lightning-sunbird  0.9+nobinonly
gtkmozbox.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org Code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Owen Taylor <otaylor@redhat.com> and Christopher Blizzard 
00020  * <blizzard@redhat.com>.
00021  * Portions created by the Initial Developer are Copyright (C) 1999
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "gtkmozbox.h"
00041 #include <gtk/gtkmain.h>
00042 #include <X11/Xlib.h>
00043 
00044 static void            gtk_mozbox_class_init      (GtkMozBoxClass *klass);
00045 static void            gtk_mozbox_init            (GtkMozBox      *mozbox);
00046 static void            gtk_mozbox_realize         (GtkWidget      *widget);
00047 static void            gtk_mozbox_set_focus       (GtkWindow      *window,
00048                                                    GtkWidget      *focus);
00049 static gint            gtk_mozbox_key_press_event (GtkWidget   *widget,
00050                                                    GdkEventKey *event);
00051 static GdkFilterReturn gtk_mozbox_filter          (GdkXEvent      *xevent,
00052                                                    GdkEvent       *event,
00053                                                    gpointer        data);
00054 static GtkWindow *     gtk_mozbox_get_parent_gtkwindow (GtkMozBox *mozbox);
00055 
00056 void (*parent_class_set_focus)(GtkWindow *, GtkWidget *);
00057 
00058 GtkType
00059 gtk_mozbox_get_type (void)
00060 {
00061   static GtkType mozbox_type = 0;
00062 
00063   if (!mozbox_type)
00064     {
00065       static const GtkTypeInfo mozbox_info =
00066       {
00067         "GtkMozBox",
00068         sizeof (GtkMozBox),
00069         sizeof (GtkMozBoxClass),
00070         (GtkClassInitFunc) gtk_mozbox_class_init,
00071         (GtkObjectInitFunc) gtk_mozbox_init,
00072         /* reserved_1 */ NULL,
00073         /* reserved_2 */ NULL,
00074         (GtkClassInitFunc) NULL
00075       };
00076 
00077       mozbox_type = gtk_type_unique (GTK_TYPE_WINDOW, &mozbox_info);
00078     }
00079 
00080   return mozbox_type;
00081 }
00082 
00083 static void
00084 gtk_mozbox_class_init (GtkMozBoxClass *klass)
00085 {
00086   GtkWidgetClass *widget_class;
00087   GtkWindowClass *window_class;
00088 
00089   widget_class = GTK_WIDGET_CLASS (klass);
00090   window_class = GTK_WINDOW_CLASS (klass);
00091 
00092   widget_class->realize         = gtk_mozbox_realize;
00093   widget_class->key_press_event = gtk_mozbox_key_press_event;
00094 
00095   /* save the parent class' set_focus method */
00096   parent_class_set_focus = window_class->set_focus;
00097   window_class->set_focus       = gtk_mozbox_set_focus;
00098   
00099 }
00100 
00101 static void
00102 gtk_mozbox_init (GtkMozBox *mozbox)
00103 {
00104   mozbox->parent_window = NULL;
00105   mozbox->x = 0;
00106   mozbox->y = 0;
00107 }
00108 
00109 static void
00110 gtk_mozbox_realize (GtkWidget *widget)
00111 {
00112   GdkWindowAttr attributes;
00113   gint attributes_mask;
00114   GtkMozBox *mozbox;
00115 
00116   g_return_if_fail (GTK_IS_MOZBOX (widget));
00117 
00118   mozbox = GTK_MOZBOX (widget);
00119 
00120   /* GtkWindow checks against premature realization here. Just
00121    * don't do it.
00122    */
00123   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
00124 
00125   attributes.window_type = GDK_WINDOW_CHILD;
00126   attributes.x = mozbox->x;
00127   attributes.y = mozbox->y;
00128   attributes.width = widget->allocation.width;
00129   attributes.height = widget->allocation.height;
00130   attributes.wclass = GDK_INPUT_OUTPUT;
00131   attributes.visual = gtk_widget_get_visual (widget);
00132   attributes.colormap = gtk_widget_get_colormap (widget);
00133   attributes.event_mask = gtk_widget_get_events (widget);
00134   attributes.event_mask |= GDK_EXPOSURE_MASK;
00135   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
00136 
00137   widget->window = gdk_window_new (mozbox->parent_window,
00138                                &attributes, attributes_mask);
00139 
00140   /* set the back pixmap to None so that you don't end up with the gtk
00141      default which is BlackPixel */
00142   gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
00143 
00144   gdk_window_set_user_data (widget->window, mozbox);
00145 
00146   widget->style = gtk_style_attach (widget->style, widget->window);
00147   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
00148 
00149   gdk_window_add_filter (widget->window, gtk_mozbox_filter, mozbox);
00150 }
00151 
00152 static void
00153 gtk_mozbox_set_focus (GtkWindow      *window,
00154                       GtkWidget      *focus)
00155 {
00156   GtkMozBox *mozbox;
00157   GdkWindow *tmpWindow;
00158   GtkWindow *parentGtkWindow;
00159 
00160   g_return_if_fail(window != NULL);
00161   g_return_if_fail(GTK_IS_MOZBOX(window));
00162 
00163   mozbox = GTK_MOZBOX(window);
00164 
00165   parentGtkWindow = gtk_mozbox_get_parent_gtkwindow (mozbox);
00166 
00167   if (parentGtkWindow) {
00168     parent_class_set_focus(parentGtkWindow, focus);
00169     return;
00170   }
00171 
00172   /* as a fall back just hand it off to our parent class */
00173   parent_class_set_focus(window, focus);
00174 
00175 }
00176 
00177 static gint
00178 gtk_mozbox_key_press_event (GtkWidget   *widget,
00179                             GdkEventKey *event)
00180 {
00181   GtkWindow *window;
00182   GtkMozBox *mozbox;
00183   GtkWindow *parentWindow;
00184   gboolean   handled = FALSE;
00185 
00186   window = GTK_WINDOW (widget);
00187   mozbox = GTK_MOZBOX (widget);
00188 
00189   parentWindow = gtk_mozbox_get_parent_gtkwindow(mozbox);
00190 
00191   /* give the focus window the chance to handle the event first. */
00192   if (parentWindow && parentWindow->focus_widget) {
00193     handled = gtk_widget_event (parentWindow->focus_widget, (GdkEvent*) event);
00194   }
00195 
00196   /* pass it off to the parent widget */
00197   if (!handled) {
00198     gdk_window_unref(event->window);
00199     event->window = mozbox->parent_window;
00200     gdk_window_ref(event->window);
00201     gdk_event_put((GdkEvent *)event);
00202   }
00203 
00204   return TRUE;
00205 }
00206 
00207 static GdkFilterReturn 
00208 gtk_mozbox_filter (GdkXEvent *xevent,
00209                  GdkEvent *event,
00210                  gpointer  data)
00211 {
00212   XEvent *xev = xevent;
00213   GtkWidget *widget = data;
00214 
00215   switch (xev->xany.type)
00216     {
00217     case ConfigureNotify:
00218       event->configure.type = GDK_CONFIGURE;
00219       event->configure.window = widget->window;
00220       event->configure.x = 0;
00221       event->configure.y = 0;
00222       event->configure.width = xev->xconfigure.width;
00223       event->configure.height = xev->xconfigure.height;
00224       return GDK_FILTER_TRANSLATE;
00225     default:
00226       return GDK_FILTER_CONTINUE;
00227     }
00228 }
00229 
00230 static GtkWindow *
00231 gtk_mozbox_get_parent_gtkwindow (GtkMozBox *mozbox)
00232 {
00233   GdkWindow *tmpWindow;
00234   /* look for a parent GtkWindow in the heirarchy */
00235   tmpWindow = mozbox->parent_window;
00236   while (tmpWindow) {
00237     gpointer data = NULL;
00238     gdk_window_get_user_data(tmpWindow, &data);
00239     if (data && GTK_IS_WINDOW(data)) {
00240       return GTK_WINDOW(data);
00241     }
00242     tmpWindow = gdk_window_get_parent(tmpWindow);
00243   }
00244   return NULL;
00245 }
00246 
00247 GtkWidget*
00248 gtk_mozbox_new (GdkWindow *parent_window)
00249 {
00250   GtkMozBox *mozbox;
00251 
00252   mozbox = gtk_type_new (GTK_TYPE_MOZBOX);
00253   mozbox->parent_window = parent_window;
00254 
00255   return GTK_WIDGET (mozbox);
00256 }
00257 
00258 void
00259 gtk_mozbox_set_position (GtkMozBox *mozbox,
00260                       gint       x,
00261                       gint       y)
00262 {
00263   mozbox->x = x;
00264   mozbox->y = y;
00265 
00266   if (GTK_WIDGET_REALIZED (mozbox))
00267     gdk_window_move (GTK_WIDGET (mozbox)->window, x, y);
00268 }
00269