Added layout widget for scrolling arbitrarily big areas. Added plug/socket

Mon Nov 23 22:10:09 1998  Owen Taylor  <otaylor@redhat.com>

	* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
	gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:

	Added layout widget for scrolling arbitrarily big areas.
	Added plug/socket widgets for interprocess embedding.

	These widgets still, at some point, need to be
	made more pure in their use of GDK, as opposed
	to raw X.

	* gtk/testgtk.c: Added test for layout widget.
This commit is contained in:
Owen Taylor 1998-11-24 04:45:29 +00:00 committed by Owen Taylor
parent 42faec1736
commit ee1d43929c
21 changed files with 2882 additions and 5 deletions

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -1,3 +1,17 @@
Mon Nov 23 22:10:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/Makefile.am gtk/gtk.h gtk/gtklayout.[ch]
gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/gtk.h:
Added layout widget for scrolling arbitrarily big areas.
Added plug/socket widgets for interprocess embedding.
These widgets still, at some point, need to be
made more pure in their use of GDK, as opposed
to raw X.
* gtk/testgtk.c: Added test for layout widget.
1998-11-23 Jeff Garzik <jgarzik@pobox.com>
* gtk/gtkclist.c: (gtk_clist_swap_rows): Bugfix from

View File

@ -3,7 +3,7 @@
SRC_SUBDIRS = gdk gtk
SUBDIRS = $(SRC_SUBDIRS) docs
bin_SCRIPTS = gtk-config
bbin_SCRIPTS = gtk-config
EXTRA_DIST = \
HACKING \

4
TODO
View File

@ -110,10 +110,6 @@ Additions:
gtk_widget_dnd_data_set (should be guchar * with a copy?
shouldn't be there at all...)
* gtk_rc_add_[name/class]_style are broken for bg pixmaps, because
styles are broken for bg pixmaps, and RC styles only hack around
that.
* Try to rationally deal with someone else deleting one of our
windows??? This would mean keeping track of our window heirarchy
ourselves, for one thing, and will never be safe, because of

View File

@ -55,6 +55,7 @@ static_sources = \
gtkitem.c \
gtkitemfactory.c \
gtklabel.c \
gtklayout.c \
gtklist.c \
gtklistitem.c \
gtkmain.c \
@ -70,6 +71,7 @@ static_sources = \
gtkpacker.c \
gtkpaned.c \
gtkpixmap.c \
gtkplug.c \
gtkpreview.c \
gtkprogress.c \
gtkprogressbar.c \
@ -84,6 +86,7 @@ static_sources = \
gtkselection.c \
gtkseparator.c \
gtksignal.c \
gtksocket.c \
gtkspinbutton.c \
gtkstyle.c \
gtkstatusbar.c \
@ -169,6 +172,7 @@ source_headers = \
gtkitem.h \
gtkitemfactory.h \
gtklabel.h \
gtklayout.h \
gtklist.h \
gtklistitem.h \
gtkmain.h \
@ -184,6 +188,7 @@ source_headers = \
gtkpacker.h \
gtkpaned.h \
gtkpixmap.h \
gtkplug.h \
gtkpreview.h \
gtkprivate.h \
gtkprogress.h \
@ -199,6 +204,7 @@ source_headers = \
gtkselection.h \
gtkseparator.h \
gtksignal.h \
gtksocket.h \
gtkspinbutton.h \
gtkstyle.h \
gtkstatusbar.h \

View File

@ -71,6 +71,7 @@
#include <gtk/gtkitem.h>
#include <gtk/gtkitemfactory.h>
#include <gtk/gtklabel.h>
#include <gtk/gtklayout.h>
#include <gtk/gtklist.h>
#include <gtk/gtklistitem.h>
#include <gtk/gtkmain.h>
@ -86,6 +87,7 @@
#include <gtk/gtkpacker.h>
#include <gtk/gtkpaned.h>
#include <gtk/gtkpixmap.h>
#include <gtk/gtkplug.h>
#include <gtk/gtkpreview.h>
#include <gtk/gtkprogress.h>
#include <gtk/gtkprogressbar.h>
@ -100,6 +102,7 @@
#include <gtk/gtkselection.h>
#include <gtk/gtkseparator.h>
#include <gtk/gtksignal.h>
#include <gtk/gtksocket.h>
#include <gtk/gtkspinbutton.h>
#include <gtk/gtkstyle.h>
#include <gtk/gtkstatusbar.h>

1207
gtk/gtklayout.c Normal file

File diff suppressed because it is too large Load Diff

104
gtk/gtklayout.h Normal file
View File

@ -0,0 +1,104 @@
/* Copyright Owen Taylor, 1998
*
* This file may be distributed under either the terms of the
* Netscape Public License, or the GNU Library General Public License
*
* Note: No GTK+ or Mozilla code should be added to this file.
* The coding style should be that of the the GTK core.
*/
#ifndef __GTK_LAYOUT_H
#define __GTK_LAYOUT_H
#include <gdk/gdk.h>
#include <gtk/gtkcontainer.h>
#include <gtk/gtkadjustment.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_LAYOUT(obj) GTK_CHECK_CAST (obj, gtk_layout_get_type (), GtkLayout)
#define GTK_LAYOUT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_layout_get_type (), GtkLayoutClass)
#define GTK_IS_LAYOUT(obj) GTK_CHECK_TYPE (obj, gtk_layout_get_type ())
typedef struct _GtkLayout GtkLayout;
typedef struct _GtkLayoutClass GtkLayoutClass;
typedef struct _GtkLayoutChild GtkLayoutChild;
struct _GtkLayoutChild {
GtkWidget *widget;
GdkWindow *window; /* For NO_WINDOW widgets */
gint x;
gint y;
};
struct _GtkLayout {
GtkContainer container;
GList *children;
guint width;
guint height;
guint xoffset;
guint yoffset;
GtkAdjustment *hadjustment;
GtkAdjustment *vadjustment;
GdkWindow *bin_window;
GdkVisibilityState visibility;
gulong configure_serial;
gint scroll_x;
gint scroll_y;
guint frozen : 1;
};
struct _GtkLayoutClass {
GtkContainerClass parent_class;
void (*scroll_adjustments) (GtkLayout *text,
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
};
GtkWidget* gtk_layout_new (GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
guint gtk_layout_get_type (void);
void gtk_layout_put (GtkLayout *layout,
GtkWidget *widget,
gint x,
gint y);
void gtk_layout_move (GtkLayout *layout,
GtkWidget *widget,
gint x,
gint y);
void gtk_layout_set_size (GtkLayout *layout,
guint width,
guint height);
/* These disable and enable moving and repainting the scrolling window of the GtkLayout,
* respectively. If you want to update the layout's offsets but do not want it to
* repaint itself, you should use these functions.
*/
void gtk_layout_freeze (GtkLayout *layout);
void gtk_layout_thaw (GtkLayout *layout);
GtkAdjustment* gtk_layout_get_hadjustment (GtkLayout *layout);
GtkAdjustment* gtk_layout_get_vadjustment (GtkLayout *layout);
void gtk_layout_set_hadjustment (GtkLayout *layout,
GtkAdjustment *adjustment);
void gtk_layout_set_vadjustment (GtkLayout *layout,
GtkAdjustment *adjustment);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_LAYOUT_H */

409
gtk/gtkplug.c Normal file
View File

@ -0,0 +1,409 @@
/* GTK - The GIMP Toolkit
* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* By Owen Taylor <otaylor@gtk.org> 98/4/4 */
#include "gdk/gdkx.h"
#include "gdk/gdkkeysyms.h"
#include "gtkplug.h"
static void gtk_plug_class_init (GtkPlugClass *klass);
static void gtk_plug_init (GtkPlug *plug);
static void gtk_plug_realize (GtkWidget *widget);
static gint gtk_plug_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event);
static gint gtk_plug_focus_in_event (GtkWidget *widget, GdkEventFocus *event);
static gint gtk_plug_focus_out_event (GtkWidget *widget, GdkEventFocus *event);
static void gtk_plug_set_focus (GtkWindow *window,
GtkWidget *focus);
/* From Tk */
#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
guint
gtk_plug_get_type ()
{
static guint plug_type = 0;
if (!plug_type)
{
GtkTypeInfo plug_info =
{
"GtkPlug",
sizeof (GtkPlug),
sizeof (GtkPlugClass),
(GtkClassInitFunc) gtk_plug_class_init,
(GtkObjectInitFunc) gtk_plug_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
plug_type = gtk_type_unique (gtk_window_get_type (), &plug_info);
}
return plug_type;
}
static void
gtk_plug_class_init (GtkPlugClass *class)
{
GtkWidgetClass *widget_class;
GtkWindowClass *window_class;
widget_class = (GtkWidgetClass *)class;
window_class = (GtkWindowClass *)class;
widget_class->realize = gtk_plug_realize;
widget_class->key_press_event = gtk_plug_key_press_event;
widget_class->focus_in_event = gtk_plug_focus_in_event;
widget_class->focus_out_event = gtk_plug_focus_out_event;
window_class->set_focus = gtk_plug_set_focus;
}
static void
gtk_plug_init (GtkPlug *plug)
{
GtkWindow *window;
window = GTK_WINDOW (plug);
window->type = GTK_WINDOW_TOPLEVEL;
window->auto_shrink = TRUE;
}
void
gtk_plug_construct (GtkPlug *plug, guint32 socket_id)
{
plug->socket_window = gdk_window_lookup (socket_id);
plug->same_app = TRUE;
if (plug->socket_window == NULL)
{
plug->socket_window = gdk_window_foreign_new (socket_id);
plug->same_app = FALSE;
}
}
GtkWidget*
gtk_plug_new (guint32 socket_id)
{
GtkPlug *plug;
plug = GTK_PLUG (gtk_type_new (gtk_plug_get_type ()));
gtk_plug_construct (plug, socket_id);
return GTK_WIDGET (plug);
}
static void
gtk_plug_realize (GtkWidget *widget)
{
GtkWindow *window;
GtkPlug *plug;
GdkWindowAttr attributes;
gint attributes_mask;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_PLUG (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
window = GTK_WINDOW (widget);
plug = GTK_PLUG (widget);
attributes.window_type = GDK_WINDOW_CHILD; /* XXX GDK_WINDOW_PLUG ? */
attributes.title = window->title;
attributes.wmclass_name = window->wmclass_name;
attributes.wmclass_class = window->wmclass_class;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
/* this isn't right - we should match our parent's visual/colormap.
* though that will require handling "foreign" colormaps */
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 |
GDK_KEY_PRESS_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_STRUCTURE_MASK);
attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
widget->window = gdk_window_new (plug->socket_window,
&attributes, attributes_mask);
((GdkWindowPrivate *)widget->window)->window_type = GDK_WINDOW_TOPLEVEL;
gdk_window_set_user_data (widget->window, window);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}
static gint
gtk_plug_key_press_event (GtkWidget *widget,
GdkEventKey *event)
{
GtkWindow *window;
GtkPlug *plug;
GtkDirectionType direction = 0;
gint return_val;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
window = GTK_WINDOW (widget);
plug = GTK_PLUG (widget);
if (!GTK_WIDGET_HAS_FOCUS(widget))
{
gtk_plug_forward_key_press (plug, event);
return TRUE;
}
return_val = FALSE;
if (window->focus_widget)
return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
#if 0
if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
return_val = TRUE;
#endif
if (!return_val)
{
switch (event->keyval)
{
case GDK_space:
if (window->focus_widget)
{
gtk_widget_activate (window->focus_widget);
return_val = TRUE;
}
break;
case GDK_Return:
case GDK_KP_Enter:
if (window->default_widget)
{
gtk_widget_activate (window->default_widget);
return_val = TRUE;
}
else if (window->focus_widget)
{
gtk_widget_activate (window->focus_widget);
return_val = TRUE;
}
break;
case GDK_Up:
case GDK_Down:
case GDK_Left:
case GDK_Right:
case GDK_Tab:
switch (event->keyval)
{
case GDK_Up:
direction = GTK_DIR_UP;
break;
case GDK_Down:
direction = GTK_DIR_DOWN;
break;
case GDK_Left:
direction = GTK_DIR_LEFT;
break;
case GDK_Right:
direction = GTK_DIR_RIGHT;
break;
case GDK_Tab:
if (event->state & GDK_SHIFT_MASK)
direction = GTK_DIR_TAB_BACKWARD;
else
direction = GTK_DIR_TAB_FORWARD;
break;
default :
direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
}
gtk_container_focus (GTK_CONTAINER (widget), direction);
if (!GTK_CONTAINER (window)->focus_child)
{
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (plug->socket_window),
RevertToParent, event->time);
gtk_plug_forward_key_press (plug, event);
}
return_val = TRUE;
break;
}
}
return return_val;
}
static void
gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event)
{
XEvent xevent;
xevent.xkey.type = KeyPress;
xevent.xkey.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
xevent.xkey.window = GDK_WINDOW_XWINDOW (plug->socket_window);
xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
xevent.xkey.time = event->time;
/* FIXME, the following might cause big problems for
* non-GTK apps */
xevent.xkey.x = 0;
xevent.xkey.y = 0;
xevent.xkey.x_root = 0;
xevent.xkey.y_root = 0;
xevent.xkey.state = event->state;
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(),
event->keyval);
xevent.xkey.same_screen = TRUE; /* FIXME ? */
XSendEvent (gdk_display,
GDK_WINDOW_XWINDOW (plug->socket_window),
False, NoEventMask, &xevent);
}
/* Copied from Window, Ughh */
static gint
gtk_plug_focus_in_event (GtkWidget *widget,
GdkEventFocus *event)
{
GtkWindow *window;
GdkEventFocus fevent;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
/* It appears spurious focus in events can occur when
* the window is hidden. So we'll just check to see if
* the window is visible before actually handling the
* event
*/
if (GTK_WIDGET_VISIBLE (widget))
{
GTK_OBJECT_SET_FLAGS (widget, GTK_HAS_FOCUS);
window = GTK_WINDOW (widget);
if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
{
fevent.type = GDK_FOCUS_CHANGE;
fevent.window = window->focus_widget->window;
fevent.in = TRUE;
gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
}
}
return FALSE;
}
static gint
gtk_plug_focus_out_event (GtkWidget *widget,
GdkEventFocus *event)
{
GtkWindow *window;
GdkEventFocus fevent;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
GTK_OBJECT_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
window = GTK_WINDOW (widget);
if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
{
fevent.type = GDK_FOCUS_CHANGE;
fevent.window = window->focus_widget->window;
fevent.in = FALSE;
gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
}
return FALSE;
}
static void
gtk_plug_set_focus (GtkWindow *window,
GtkWidget *focus)
{
GtkPlug *plug;
GdkEventFocus event;
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_PLUG (window));
plug = GTK_PLUG (window);
if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
return;
if (window->focus_widget != focus)
{
if (window->focus_widget)
{
event.type = GDK_FOCUS_CHANGE;
event.window = window->focus_widget->window;
event.in = FALSE;
gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
}
window->focus_widget = focus;
if (window->focus_widget)
{
event.type = GDK_FOCUS_CHANGE;
event.window = window->focus_widget->window;
event.in = TRUE;
gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
}
}
/* Ask for focus from parent */
if (focus && !GTK_WIDGET_HAS_FOCUS(window))
{
XEvent xevent;
xevent.xfocus.type = FocusIn;
xevent.xfocus.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
xevent.xfocus.window = GDK_WINDOW_XWINDOW (plug->socket_window);
xevent.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
xevent.xfocus.detail = FALSE; /* Don't force */
XSendEvent (gdk_display,
GDK_WINDOW_XWINDOW (plug->socket_window),
False, NoEventMask, &xevent);
}
}

65
gtk/gtkplug.h Normal file
View File

@ -0,0 +1,65 @@
/* GTK - The GIMP Toolkit
* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __GTK_PLUG_H__
#define __GTK_PLUG_H__
#include <gdk/gdk.h>
#include <gtk/gtkwindow.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_PLUG(obj) GTK_CHECK_CAST (obj, gtk_plug_get_type (), GtkPlug)
#define GTK_PLUG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_plug_get_type (), GtkPlugClass)
#define GTK_IS_PLUG(obj) GTK_CHECK_TYPE (obj, gtk_plug_get_type ())
typedef struct _GtkPlug GtkPlug;
typedef struct _GtkPlugClass GtkPlugClass;
typedef struct _GtkPlugButton GtkPlugButton;
struct _GtkPlug
{
GtkWindow window;
GdkWindow *socket_window;
gint same_app;
};
struct _GtkPlugClass
{
GtkWindowClass parent_class;
};
guint gtk_plug_get_type (void);
void gtk_plug_construct (GtkPlug *plug, guint32 socket_id);
GtkWidget* gtk_plug_new (guint32 socket_id);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_PLUG_H__ */

688
gtk/gtksocket.c Normal file
View File

@ -0,0 +1,688 @@
/* GTK - The GIMP Toolkit
* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* By Owen Taylor <otaylor@gtk.org> 98/4/4 */
#include "gdk/gdkx.h"
#include "gdk/gdkkeysyms.h"
#include "gtkwindow.h"
#include "gtksignal.h"
#include "gtksocket.h"
#include "gtkdnd.h"
/* Forward declararations */
static void gtk_socket_class_init (GtkSocketClass *klass);
static void gtk_socket_init (GtkSocket *socket);
static void gtk_socket_realize (GtkWidget *widget);
static void gtk_socket_unrealize (GtkWidget *widget);
static void gtk_socket_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_socket_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static gint gtk_socket_focus_in_event (GtkWidget *widget,
GdkEventFocus *event);
static void gtk_socket_claim_focus (GtkSocket *socket);
static gint gtk_socket_focus_out_event (GtkWidget *widget,
GdkEventFocus *event);
static void gtk_socket_send_configure_event (GtkSocket *socket);
static gint gtk_socket_focus (GtkContainer *container,
GtkDirectionType direction);
static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data);
#ifdef DEBUG_PLUGSOCKET
#define DPRINTF(arg) g_print arg
#else
#define DPRINTF(arg)
#endif
/* From Tk */
#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
/* Local data */
static GtkWidgetClass *parent_class = NULL;
guint
gtk_socket_get_type ()
{
static guint socket_type = 0;
if (!socket_type)
{
GtkTypeInfo socket_info =
{
"GtkSocket",
sizeof (GtkSocket),
sizeof (GtkSocketClass),
(GtkClassInitFunc) gtk_socket_class_init,
(GtkObjectInitFunc) gtk_socket_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
socket_type = gtk_type_unique (gtk_container_get_type (), &socket_info);
}
return socket_type;
}
static void
gtk_socket_class_init (GtkSocketClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
container_class = (GtkContainerClass*) class;
parent_class = gtk_type_class (gtk_widget_get_type ());
widget_class->realize = gtk_socket_realize;
widget_class->unrealize = gtk_socket_unrealize;
widget_class->size_request = gtk_socket_size_request;
widget_class->size_allocate = gtk_socket_size_allocate;
widget_class->focus_in_event = gtk_socket_focus_in_event;
widget_class->focus_out_event = gtk_socket_focus_out_event;
container_class->focus = gtk_socket_focus;
}
static void
gtk_socket_init (GtkSocket *socket)
{
socket->request_width = 0;
socket->request_height = 0;
socket->current_width = 0;
socket->current_height = 0;
socket->plug_window = NULL;
socket->same_app = FALSE;
socket->focus_in = FALSE;
socket->have_size = FALSE;
socket->need_map = FALSE;
}
GtkWidget*
gtk_socket_new ()
{
GtkSocket *socket;
socket = gtk_type_new (gtk_socket_get_type ());
return GTK_WIDGET (socket);
}
void
gtk_socket_steal (GtkSocket *socket, guint32 id)
{
GtkWidget *widget;
widget = GTK_WIDGET (socket);
socket->plug_window = gdk_window_lookup (id);
if (socket->plug_window && socket->plug_window->user_data)
{
GtkWidget *child_widget = GTK_WIDGET (socket->plug_window->user_data);
g_warning("Stealing from same app not yet implemented");
socket->same_app = TRUE;
}
else
{
socket->plug_window = gdk_window_foreign_new (id);
socket->same_app = FALSE;
socket->have_size = FALSE;
XSelectInput (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW(socket->plug_window),
StructureNotifyMask | PropertyChangeMask);
gtk_widget_queue_resize (widget);
}
gdk_window_hide (socket->plug_window);
gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
socket->need_map = TRUE;
}
static void
gtk_socket_realize (GtkWidget *widget)
{
GtkSocket *socket;
GdkWindowAttr attributes;
gint attributes_mask;
XWindowAttributes xattrs;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SOCKET (widget));
socket = GTK_SOCKET (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.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 = GDK_FOCUS_CHANGE_MASK;
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
&attributes, attributes_mask);
gdk_window_set_user_data (widget->window, socket);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
XGetWindowAttributes (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (widget->window),
&xattrs);
XSelectInput (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW(widget->window),
xattrs.your_event_mask |
SubstructureNotifyMask | SubstructureRedirectMask);
gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
/* We sync here so that we make sure that if the XID for
* our window is passed to another application, SubstructureRedirectMask
* will be set by the time the other app creates its window.
*/
gdk_flush();
}
static void
gtk_socket_unrealize (GtkWidget *widget)
{
GtkSocket *socket;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SOCKET (widget));
socket = GTK_SOCKET (widget);
if (socket->plug_window)
{
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
if (toplevel && GTK_IS_WINDOW (toplevel))
gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel),
GDK_WINDOW_XWINDOW (socket->plug_window));
}
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}
static void
gtk_socket_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkSocket *socket;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SOCKET (widget));
g_return_if_fail (requisition != NULL);
socket = GTK_SOCKET (widget);
if (!socket->have_size && socket->plug_window)
{
XSizeHints hints;
long supplied;
if (XGetWMNormalHints (GDK_DISPLAY(),
GDK_WINDOW_XWINDOW (socket->plug_window),
&hints, &supplied))
{
/* This is obsolete, according the X docs, but many programs
* still use it */
if (hints.flags & (PSize | USSize))
{
socket->request_width = hints.width;
socket->request_height = hints.height;
}
else if (hints.flags & PMinSize)
{
socket->request_width = hints.min_width;
socket->request_height = hints.min_height;
}
else if (hints.flags & PBaseSize)
{
socket->request_width = hints.base_width;
socket->request_height = hints.base_height;
}
}
socket->have_size = TRUE; /* don't check again? */
}
requisition->width = socket->request_width;
requisition->height = socket->request_height;
}
static void
gtk_socket_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkSocket *socket;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SOCKET (widget));
g_return_if_fail (allocation != NULL);
socket = GTK_SOCKET (widget);
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
if (socket->plug_window)
{
if (!socket->need_map &&
(allocation->width == socket->current_width) &&
(allocation->height == socket->current_height))
{
gtk_socket_send_configure_event (socket);
DPRINTF(( "No change: %d %d\n",
allocation->width, allocation->height));
}
else
{
gdk_window_move_resize (socket->plug_window,
0, 0,
allocation->width, allocation->height);
DPRINTF(("configuring: %d %d\n",
allocation->width, allocation->height));
socket->current_width = allocation->width;
socket->current_height = allocation->height;
}
if (socket->need_map)
{
gdk_window_show (socket->plug_window);
socket->need_map = FALSE;
}
}
}
}
static gint
gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
{
GtkSocket *socket;
g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
socket = GTK_SOCKET (widget);
DPRINTF (( "Got focus\n"));
if (socket->focus_in && socket->plug_window)
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (socket->plug_window),
RevertToParent, GDK_CURRENT_TIME);
return TRUE;
}
static gint
gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
{
GtkWidget *toplevel;
GtkSocket *socket;
g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
socket = GTK_SOCKET (widget);
toplevel = gtk_widget_get_ancestor (widget, gtk_window_get_type());
if (toplevel)
{
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (toplevel->window),
RevertToParent, CurrentTime); /* FIXME? */
}
socket->focus_in = FALSE;
return TRUE;
}
static void
gtk_socket_claim_focus (GtkSocket *socket)
{
socket->focus_in = TRUE;
/* Oh, the trickery... */
GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
gtk_widget_grab_focus (GTK_WIDGET (socket));
GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
/* FIXME: we might grab the focus even if we don't have
* it as an app... (and see _focus_in ()) */
if (socket->plug_window)
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (socket->plug_window),
RevertToParent, GDK_CURRENT_TIME);
}
static gint
gtk_socket_focus (GtkContainer *container, GtkDirectionType direction)
{
GtkSocket *socket;
g_return_val_if_fail (GTK_IS_SOCKET (container), FALSE);
socket = GTK_SOCKET (container);
if (!socket->focus_in && socket->plug_window)
{
XEvent xevent;
gtk_socket_claim_focus (socket);
xevent.xkey.type = KeyPress;
xevent.xkey.display = GDK_DISPLAY ();
xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
xevent.xkey.time = GDK_CURRENT_TIME; /* FIXME */
/* FIXME, the following might cause big problems for
* non-GTK apps */
xevent.xkey.x = 0;
xevent.xkey.y = 0;
xevent.xkey.x_root = 0;
xevent.xkey.y_root = 0;
xevent.xkey.state = 0;
xevent.xkey.same_screen = TRUE; /* FIXME ? */
switch (direction)
{
case GTK_DIR_UP:
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Up);
break;
case GTK_DIR_DOWN:
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Down);
break;
case GTK_DIR_LEFT:
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Left);
break;
case GTK_DIR_RIGHT:
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Right);
break;
case GTK_DIR_TAB_FORWARD:
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
break;
case GTK_DIR_TAB_BACKWARD:
xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
xevent.xkey.state = ShiftMask;
break;
}
XSendEvent (gdk_display,
GDK_WINDOW_XWINDOW (socket->plug_window),
False, NoEventMask, &xevent);
return TRUE;
}
else
{
return FALSE;
}
}
static void
gtk_socket_send_configure_event (GtkSocket *socket)
{
XEvent event;
g_return_if_fail (socket->plug_window != NULL);
event.xconfigure.type = ConfigureNotify;
event.xconfigure.display = gdk_display;
event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
event.xconfigure.x = 0;
event.xconfigure.y = 0;
event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
event.xconfigure.border_width = 0;
event.xconfigure.above = None;
event.xconfigure.override_redirect = False;
XSendEvent (gdk_display,
GDK_WINDOW_XWINDOW (socket->plug_window),
False, NoEventMask, &event);
}
static void
gtk_socket_add_window (GtkSocket *socket, guint32 xid)
{
socket->plug_window = gdk_window_lookup (xid);
socket->same_app = TRUE;
if (!socket->plug_window)
{
GtkWidget *toplevel;
GdkDragProtocol protocol;
socket->plug_window = gdk_window_foreign_new (xid);
socket->same_app = FALSE;
XSelectInput (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW(socket->plug_window),
StructureNotifyMask | PropertyChangeMask);
if (gdk_drag_get_protocol (xid, &protocol))
gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window,
protocol, TRUE);
gdk_window_add_filter (socket->plug_window,
gtk_socket_filter_func, socket);
/* Add a pointer to the socket on our toplevel window */
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
if (toplevel && GTK_IS_WINDOW (toplevel))
{
gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
}
}
}
static GdkFilterReturn
gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
{
GtkSocket *socket;
GtkWidget *widget;
XEvent *xevent;
GdkFilterReturn return_val;
socket = GTK_SOCKET (data);
widget = GTK_WIDGET (socket);
xevent = (XEvent *)gdk_xevent;
return_val = GDK_FILTER_CONTINUE;
switch (xevent->type)
{
case CreateNotify:
{
XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
if (!socket->plug_window)
{
g_print("Here!\n");
gtk_socket_add_window (socket, xcwe->window);
gdk_window_move_resize(socket->plug_window,
0, 0,
widget->allocation.width,
widget->allocation.height);
socket->request_width = xcwe->width;
socket->request_height = xcwe->height;
socket->have_size = TRUE;
DPRINTF(("Window created with size: %d %d\n",
socket->request_width,
socket->request_height));
gtk_widget_queue_resize (widget);
}
return_val = GDK_FILTER_REMOVE;
break;
}
case ConfigureRequest:
{
XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
if (!socket->plug_window)
gtk_socket_add_window (socket, xcre->window);
if (xcre->window == GDK_WINDOW_XWINDOW (socket->plug_window))
{
if (xcre->value_mask & (CWWidth | CWHeight))
{
socket->request_width = xcre->width;
socket->request_height = xcre->height;
socket->have_size = TRUE;
DPRINTF(("Configure request: %d %d\n",
socket->request_width,
socket->request_height));
gtk_widget_queue_resize (widget);
}
else if (xcre->value_mask & (CWX | CWY))
{
gtk_socket_send_configure_event (socket);
}
/* Ignore stacking requests. */
return_val = GDK_FILTER_REMOVE;
}
break;
}
case DestroyNotify:
{
XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
if (socket->plug_window &&
(xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
{
GtkWidget *toplevel;
DPRINTF(("Destroy Notify\n"));
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
if (toplevel && GTK_IS_WINDOW (toplevel))
gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window);
gtk_widget_destroy (widget);
gdk_window_destroy_notify (socket->plug_window);
socket->plug_window = NULL;
return_val = GDK_FILTER_REMOVE;
}
break;
}
case FocusIn:
if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
{
gtk_socket_claim_focus (socket);
}
else if (xevent->xfocus.detail == NotifyInferior)
{
#if 0
GtkWidget *toplevel;
toplevel = gtk_widget_get_ancestor (widget, gtk_window_get_type());
if (toplevel)
{
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (toplevel->window),
RevertToParent, CurrentTime); /* FIXME? */
}
#endif
}
return_val = GDK_FILTER_REMOVE;
break;
case FocusOut:
return_val = GDK_FILTER_REMOVE;
break;
case MapRequest:
if (!socket->plug_window)
gtk_socket_add_window (socket, xevent->xmaprequest.window);
if (xevent->xmaprequest.window ==
GDK_WINDOW_XWINDOW (socket->plug_window))
{
DPRINTF(("Map Request\n"));
gdk_window_show (socket->plug_window);
return_val = GDK_FILTER_REMOVE;
}
break;
case PropertyNotify:
if (xevent->xproperty.window ==
GDK_WINDOW_XWINDOW (socket->plug_window))
{
GdkDragProtocol protocol;
if ((xevent->xproperty.atom == gdk_atom_intern ("XdndAware", FALSE)) ||
(xevent->xproperty.atom == gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO", FALSE)))
{
if (gdk_drag_get_protocol (xevent->xproperty.window, &protocol))
gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
socket->plug_window,
protocol, TRUE);
}
return_val = GDK_FILTER_REMOVE;
}
}
return return_val;
}

68
gtk/gtksocket.h Normal file
View File

@ -0,0 +1,68 @@
/* GTK - The GIMP Toolkit
* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __GTK_SOCKET_H__
#define __GTK_SOCKET_H__
#include <gtk/gtkcontainer.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_SOCKET(obj) GTK_CHECK_CAST (obj, gtk_socket_get_type (), GtkSocket)
#define GTK_SOCKET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_socket_get_type (), GtkSocketClass)
#define GTK_IS_SOCKET(obj) GTK_CHECK_TYPE (obj, gtk_socket_get_type ())
typedef struct _GtkSocket GtkSocket;
typedef struct _GtkSocketClass GtkSocketClass;
struct _GtkSocket
{
GtkContainer container;
guint16 request_width;
guint16 request_height;
guint16 current_width;
guint16 current_height;
GdkWindow *plug_window;
guint same_app : 1;
guint focus_in : 1;
guint have_size : 1;
guint need_map : 1;
};
struct _GtkSocketClass
{
GtkContainerClass parent_class;
};
GtkWidget* gtk_socket_new (void);
guint gtk_socket_get_type (void );
void gtk_socket_steal (GtkSocket *socket,
guint32 wid);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_SOCKET_H__ */

View File

@ -464,6 +464,58 @@ gtk_window_set_modal (GtkWindow *window, gboolean modal)
window->modal = modal;
}
void
gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
{
GList *embedded_windows;
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
g_print ("add %#x\n", xid);
embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
if (embedded_windows)
gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
g_quark_from_static_string ("gtk-embedded"));
embedded_windows = g_list_prepend (embedded_windows,
GUINT_TO_POINTER (xid));
gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
embedded_windows,
embedded_windows ?
(GtkDestroyNotify) g_list_free : NULL);
}
void
gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
{
GList *embedded_windows;
GList *node;
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
g_print ("remove %#x\n", xid);
embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
if (embedded_windows)
gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
g_quark_from_static_string ("gtk-embedded"));
node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
if (node)
{
embedded_windows = g_list_remove_link (embedded_windows, node);
g_list_free_1 (node);
}
gtk_object_set_data_full (GTK_OBJECT (window),
"gtk-embedded", embedded_windows,
embedded_windows ?
(GtkDestroyNotify) g_list_free : NULL);
}
static void
gtk_window_shutdown (GtkObject *object)
{

View File

@ -100,6 +100,9 @@ gint gtk_window_activate_default (GtkWindow *window);
void gtk_window_set_modal (GtkWindow *window,
gboolean modal);
void gtk_window_remove_embedded_xid (GtkWindow *window, guint xid);
void gtk_window_add_embedded_xid (GtkWindow *window, guint xid);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -7940,6 +7940,94 @@ create_mainloop (void)
gtk_widget_destroy (window);
}
gint
layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
{
GtkLayout *layout;
gint i,j;
gint imin, imax, jmin, jmax;
layout = GTK_LAYOUT (widget);
imin = (layout->xoffset + event->area.x) / 10;
imax = (layout->xoffset + event->area.x + event->area.width + 9) / 10;
jmin = (layout->yoffset + event->area.y) / 10;
jmax = (layout->yoffset + event->area.y + event->area.height + 9) / 10;
gdk_window_clear_area (widget->window,
event->area.x, event->area.y,
event->area.width, event->area.height);
for (i=imin; i<imax; i++)
for (j=jmin; j<jmax; j++)
if ((i+j) % 2)
gdk_draw_rectangle (layout->bin_window,
widget->style->black_gc,
TRUE,
10*i - layout->xoffset, 10*j - layout->yoffset,
1+i%10, 1+j%10);
return TRUE;
}
void create_layout (void)
{
static GtkWidget *window = NULL;
GtkWidget *layout;
GtkWidget *scrolledwindow;
GtkWidget *button;
if (!window)
{
gchar buf[16];
gint i, j;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
&window);
gtk_window_set_title (GTK_WINDOW (window), "Layout");
gtk_widget_set_usize (window, 200, 200);
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (scrolledwindow);
gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
layout = gtk_layout_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
gtk_signal_connect (GTK_OBJECT (layout), "expose_event",
GTK_SIGNAL_FUNC (layout_expose_handler), NULL);
gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 1600);
gtk_widget_show (layout);
for (i=0 ; i < 16 ; i++)
for (j=0 ; j < 16 ; j++)
{
sprintf(buf, "Button %d, %d", i, j);
if ((i + j) % 2)
button = gtk_button_new_with_label (buf);
else
button = gtk_label_new (buf);
gtk_layout_put (GTK_LAYOUT (layout), button,
j*100, i*100);
gtk_widget_show (button);
}
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
}
/*
* Main Window and Exit
*/
@ -7974,6 +8062,7 @@ create_main_window (void)
{ "gamma curve", create_gamma_curve },
{ "handle box", create_handle_box },
{ "item factory", create_item_factory },
{ "layout", create_layout },
{ "list", create_list },
{ "menus", create_menus },
{ "modal window", create_modal_window },

View File

@ -7940,6 +7940,94 @@ create_mainloop (void)
gtk_widget_destroy (window);
}
gint
layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
{
GtkLayout *layout;
gint i,j;
gint imin, imax, jmin, jmax;
layout = GTK_LAYOUT (widget);
imin = (layout->xoffset + event->area.x) / 10;
imax = (layout->xoffset + event->area.x + event->area.width + 9) / 10;
jmin = (layout->yoffset + event->area.y) / 10;
jmax = (layout->yoffset + event->area.y + event->area.height + 9) / 10;
gdk_window_clear_area (widget->window,
event->area.x, event->area.y,
event->area.width, event->area.height);
for (i=imin; i<imax; i++)
for (j=jmin; j<jmax; j++)
if ((i+j) % 2)
gdk_draw_rectangle (layout->bin_window,
widget->style->black_gc,
TRUE,
10*i - layout->xoffset, 10*j - layout->yoffset,
1+i%10, 1+j%10);
return TRUE;
}
void create_layout (void)
{
static GtkWidget *window = NULL;
GtkWidget *layout;
GtkWidget *scrolledwindow;
GtkWidget *button;
if (!window)
{
gchar buf[16];
gint i, j;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
&window);
gtk_window_set_title (GTK_WINDOW (window), "Layout");
gtk_widget_set_usize (window, 200, 200);
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (scrolledwindow);
gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
layout = gtk_layout_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
gtk_signal_connect (GTK_OBJECT (layout), "expose_event",
GTK_SIGNAL_FUNC (layout_expose_handler), NULL);
gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 1600);
gtk_widget_show (layout);
for (i=0 ; i < 16 ; i++)
for (j=0 ; j < 16 ; j++)
{
sprintf(buf, "Button %d, %d", i, j);
if ((i + j) % 2)
button = gtk_button_new_with_label (buf);
else
button = gtk_label_new (buf);
gtk_layout_put (GTK_LAYOUT (layout), button,
j*100, i*100);
gtk_widget_show (button);
}
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
}
/*
* Main Window and Exit
*/
@ -7974,6 +8062,7 @@ create_main_window (void)
{ "gamma curve", create_gamma_curve },
{ "handle box", create_handle_box },
{ "item factory", create_item_factory },
{ "layout", create_layout },
{ "list", create_list },
{ "menus", create_menus },
{ "modal window", create_modal_window },