Implement extended layout for plug/socket

This commit is contained in:
Matthias Clasen 2009-12-19 01:23:58 -05:00
parent 9a48091064
commit 56edab3553
6 changed files with 175 additions and 1 deletions

View File

@ -32,6 +32,7 @@
#include "gtkplugprivate.h"
#include "x11/gdkx.h"
#include <X11/Xatom.h>
#include "gtkxembed.h"
#include "gtkalias.h"
@ -330,3 +331,29 @@ _gtk_plug_windowing_filter_func (GdkXEvent *gdk_xevent,
return return_val;
}
void
_gtk_plug_windowing_publish_natural_size (GtkPlug *plug,
GtkRequisition *requisition)
{
GtkWidget *widget = GTK_WIDGET (plug);
GdkDisplay *display;
GdkWindow *window;
gint32 data[2];
Atom property;
gtk_widget_realize (widget);
window = GTK_WIDGET (plug)->window;
display = gdk_drawable_get_display (window);
property = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE");
data[0] = requisition->width;
data[1] = requisition->height;
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XWINDOW (window), property,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char*)data, 2);
}

View File

@ -30,6 +30,7 @@
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkplug.h"
#include "gtkextendedlayout.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkplugprivate.h"
@ -721,6 +722,9 @@ static void
gtk_plug_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkBin *bin = GTK_BIN (widget);
GtkRequisition natural_size;
if (GTK_WIDGET_TOPLEVEL (widget))
GTK_WIDGET_CLASS (gtk_plug_parent_class)->size_allocate (widget, allocation);
else
@ -748,6 +752,10 @@ gtk_plug_size_allocate (GtkWidget *widget,
}
}
gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (bin->child),
NULL, &natural_size);
_gtk_plug_windowing_publish_natural_size (GTK_PLUG (widget), &natural_size);
}
static gboolean

View File

@ -138,4 +138,7 @@ GdkFilterReturn _gtk_plug_windowing_filter_func (GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data);
void _gtk_plug_windowing_publish_natural_size (GtkPlug *plug,
GtkRequisition *requisition);
#endif /* __GTK_PLUG_PRIVATE_H__ */

View File

@ -39,6 +39,7 @@
#include "gtkdnd.h"
#include "x11/gdkx.h"
#include <X11/Xatom.h>
#ifdef HAVE_XFIXES
#include <X11/extensions/Xfixes.h>
@ -122,6 +123,63 @@ _gtk_socket_windowing_size_request (GtkSocket *socket)
gdk_error_trap_pop ();
}
void
_gtk_socket_windowing_get_natural_size (GtkSocket *socket)
{
GtkSocketPrivate *priv;
GdkDisplay *display;
Atom property, type;
int format, status;
unsigned long nitems, bytes_after;
unsigned char *data;
gint32 *data_long;
priv = _gtk_socket_get_private (socket);
priv->natural_width = 1;
priv->natural_height = 1;
if (GTK_WIDGET_MAPPED (socket))
{
display = gdk_drawable_get_display (socket->plug_window);
property = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE");
gdk_error_trap_push ();
status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XWINDOW (socket->plug_window),
property, 0, 2, False, XA_CARDINAL,
&type, &format, &nitems, &bytes_after,
&data);
gdk_error_trap_pop ();
priv->have_natural_size = TRUE;
if (Success != status || !type)
return;
if (type != XA_CARDINAL)
{
g_warning ("_GTK_NATURAL_SIZE property has wrong type: %d\n", (int)type);
return;
}
if (nitems < 2)
{
g_warning ("_GTK_NATURAL_SIZE too short\n");
XFree (data);
return;
}
data_long = (gint32*) data;
priv->natural_width = MAX (1, data_long[0]);
priv->natural_height = MAX (1, data_long[1]);
XFree (data);
}
}
void
_gtk_socket_windowing_send_key_event (GtkSocket *socket,
GdkEvent *gdk_event,
@ -602,6 +660,10 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
}
return_val = GDK_FILTER_REMOVE;
}
else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE"))
{
_gtk_socket_windowing_get_natural_size (socket);
}
}
break;
case ReparentNotify:

View File

@ -37,6 +37,7 @@
#include "gtksocket.h"
#include "gtksocketprivate.h"
#include "gtkdnd.h"
#include "gtkextendedlayout.h"
#include "gtkintl.h"
#include "gtkalias.h"
@ -67,6 +68,7 @@ static void gtk_socket_forall (GtkContainer *container,
GtkCallback callback,
gpointer callback_data);
static void gtk_socket_extended_layout_interface_init (GtkExtendedLayoutIface *iface);
/* Local data */
@ -98,7 +100,10 @@ _gtk_socket_get_private (GtkSocket *socket)
return G_TYPE_INSTANCE_GET_PRIVATE (socket, GTK_TYPE_SOCKET, GtkSocketPrivate);
}
G_DEFINE_TYPE (GtkSocket, gtk_socket, GTK_TYPE_CONTAINER)
G_DEFINE_TYPE_WITH_CODE (GtkSocket, gtk_socket, GTK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_socket_extended_layout_interface_init))
static void
gtk_socket_finalize (GObject *object)
@ -185,6 +190,8 @@ gtk_socket_class_init (GtkSocketClass *class)
static void
gtk_socket_init (GtkSocket *socket)
{
GtkSocketPrivate *priv;
socket->request_width = 0;
socket->request_height = 0;
socket->current_width = 0;
@ -199,6 +206,9 @@ gtk_socket_init (GtkSocket *socket)
socket->accel_group = gtk_accel_group_new ();
g_object_set_data (G_OBJECT (socket->accel_group), I_("gtk-socket"), socket);
priv = _gtk_socket_get_private (socket);
priv->have_natural_size = FALSE;
}
/**
@ -1000,5 +1010,65 @@ _gtk_socket_advance_toplevel_focus (GtkSocket *socket,
}
}
static void
gtk_socket_extended_layout_get_desired_size (GtkExtendedLayout *layout,
GtkRequisition *minimal_size,
GtkRequisition *desired_size)
{
GtkSocket *socket = GTK_SOCKET (layout);
GtkSocketPrivate *priv;
if (socket->plug_widget)
{
gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (socket->plug_widget),
minimal_size,
desired_size);
}
else
{
priv = _gtk_socket_get_private (socket);
if (socket->is_mapped && !priv->have_natural_size && socket->plug_window)
{
_gtk_socket_windowing_size_request (socket);
_gtk_socket_windowing_get_natural_size (socket);
}
if (socket->is_mapped && priv->have_natural_size)
{
if (minimal_size)
{
minimal_size->width = MAX (socket->request_width, 1);
minimal_size->height = MAX (socket->request_height, 1);
}
if (desired_size)
{
desired_size->width = MAX (priv->natural_width, 1);
desired_size->height = MAX (priv->natural_height, 1);
}
}
else
{
if (minimal_size)
{
minimal_size->width = 1;
minimal_size->height = 1;
}
if (desired_size)
{
desired_size->width = 1;
desired_size->height = 1;
}
}
}
}
static void
gtk_socket_extended_layout_interface_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_size = gtk_socket_extended_layout_get_desired_size;
}
#define __GTK_SOCKET_C__
#include "gtkaliasdef.c"

View File

@ -31,6 +31,9 @@ typedef struct _GtkSocketPrivate GtkSocketPrivate;
struct _GtkSocketPrivate
{
gint resize_count;
gint natural_width;
gint natural_height;
gboolean have_natural_size;
};
/* In gtksocket.c: */
@ -83,6 +86,7 @@ void _gtk_socket_windowing_end_embedding_toplevel (GtkSocket *socket);
*/
void _gtk_socket_windowing_size_request (GtkSocket *socket);
void _gtk_socket_windowing_get_natural_size (GtkSocket *socket);
/*
* _gtk_socket_windowing_send_key_event:
*