|
Packit |
1069cd |
/* gtk-clutter-embed.c: Embeddable ClutterStage
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Copyright (C) 2007 OpenedHand
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* This library is free software; you can redistribute it and/or
|
|
Packit |
1069cd |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
1069cd |
* License as published by the Free Software Foundation; either
|
|
Packit |
1069cd |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
1069cd |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
1069cd |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
1069cd |
* Lesser General Public License for more details.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
1069cd |
* License along with this library. If not see <http://www.fsf.org/licensing>.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Authors:
|
|
Packit |
1069cd |
* Iain Holmes <iain@openedhand.com>
|
|
Packit |
1069cd |
* Emmanuele Bassi <ebassi@openedhand.com>
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/**
|
|
Packit |
1069cd |
* SECTION:gtk-clutter-embed
|
|
Packit |
1069cd |
* @Title: GtkClutterEmbed
|
|
Packit |
1069cd |
* @short_description: Widget for embedding a Clutter scene
|
|
Packit |
1069cd |
* @See_Also: #ClutterStage
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* #GtkClutterEmbed is a GTK+ widget embedding a #ClutterStage inside
|
|
Packit |
1069cd |
* a GTK+ application.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* By using a #GtkClutterEmbed widget is possible to build, show and
|
|
Packit |
1069cd |
* interact with a scene built using Clutter inside a GTK+ application.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* ## Event handling with GtkClutterEmbed
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Due to re-entrancy concerns, you should not use GTK event-related
|
|
Packit |
1069cd |
* API from within event handling signals emitted by Clutter actors
|
|
Packit |
1069cd |
* inside a #GtkClutterEmbed.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Event-related API, like the GTK drag and drop functions, or the
|
|
Packit |
1069cd |
* GTK grab ones, cause events to be processed inside the GDK event
|
|
Packit |
1069cd |
* loop; #GtkClutterEmbed and the Clutter event loop may use those
|
|
Packit |
1069cd |
* events to generate Clutter events, and thus emit signals on
|
|
Packit |
1069cd |
* #ClutterActors. If you use the event-related signals of a
|
|
Packit |
1069cd |
* #ClutterActor to call the GTK API, one of the two event loops
|
|
Packit |
1069cd |
* will try to re-enter into each other, and either cause a crash
|
|
Packit |
1069cd |
* or simply block your application.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* To avoid this behavior, you can either:
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* - only use GTK+ event handling signals to call event-related
|
|
Packit |
1069cd |
* GTK functions
|
|
Packit |
1069cd |
* - let the main loop re-enter, by calling event-related GTK
|
|
Packit |
1069cd |
* functions from within an idle or a timeout callback
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* You should also make sure you're not using GTK widgets that call
|
|
Packit |
1069cd |
* event-related GTK API, like the grab functions in a #GtkMenu, in
|
|
Packit |
1069cd |
* response to Clutter actor events.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* ## Using GtkClutterEmbed as a container
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Though #GtkClutterEmbed is a #GtkContainer subclass, it is not a
|
|
Packit |
1069cd |
* real GTK+ container; #GtkClutterEmbed is required to implement the
|
|
Packit |
1069cd |
* #GtkContainer virtual functions in order to embed a #GtkWidget
|
|
Packit |
1069cd |
* through the #GtkClutterActor class. Calling gtk_container_add()
|
|
Packit |
1069cd |
* on a #GtkClutterEmbed will trigger an assertion. It is strongly
|
|
Packit |
1069cd |
* advised not to override the #GtkContainer implementation when
|
|
Packit |
1069cd |
* subclassing #GtkClutterEmbed, to avoid breaking internal state.
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#include "config.h"
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#include <math.h>
|
|
Packit |
1069cd |
#include <string.h>
|
|
Packit |
1069cd |
#include "gtk-clutter-embed.h"
|
|
Packit |
1069cd |
#include "gtk-clutter-offscreen.h"
|
|
Packit |
1069cd |
#include "gtk-clutter-actor.h"
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#include <glib-object.h>
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#include <gdk/gdk.h>
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
#include <clutter/x11/clutter-x11.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_GDK)
|
|
Packit |
1069cd |
#include <clutter/gdk/clutter-gdk.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_WIN32)
|
|
Packit |
1069cd |
#include <clutter/win32/clutter-win32.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
#include <clutter/wayland/clutter-wayland.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11)
|
|
Packit |
1069cd |
#include <gdk/gdkx.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WIN32)
|
|
Packit |
1069cd |
#include <gdk/gdkwin32.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
#include <gdk/gdkwayland.h>
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
struct _GtkClutterEmbedPrivate
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
ClutterActor *stage;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
GList *children;
|
|
Packit |
1069cd |
int n_active_children;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
guint queue_redraw_id;
|
|
Packit |
1069cd |
guint queue_relayout_id;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
guint geometry_changed : 1;
|
|
Packit |
1069cd |
guint use_layout_size : 1;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
struct wl_subcompositor *subcompositor;
|
|
Packit |
1069cd |
struct wl_surface *clutter_surface;
|
|
Packit |
1069cd |
struct wl_subsurface *subsurface;
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
};
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gint num_filter = 0;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
enum
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
PROP_0,
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
PROP_USE_LAYOUT_SIZE
|
|
Packit |
1069cd |
};
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
G_DEFINE_TYPE_WITH_PRIVATE (GtkClutterEmbed, gtk_clutter_embed, GTK_TYPE_CONTAINER)
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_send_configure (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkWidget *widget;
|
|
Packit |
1069cd |
GtkAllocation allocation;
|
|
Packit |
1069cd |
GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
widget = GTK_WIDGET (embed);
|
|
Packit |
1069cd |
gtk_widget_get_allocation (widget, &allocation);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
event->configure.window = g_object_ref (gtk_widget_get_window (widget));
|
|
Packit |
1069cd |
event->configure.send_event = TRUE;
|
|
Packit |
1069cd |
event->configure.x = allocation.x;
|
|
Packit |
1069cd |
event->configure.y = allocation.y;
|
|
Packit |
1069cd |
event->configure.width = allocation.width;
|
|
Packit |
1069cd |
event->configure.height = allocation.height;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_widget_event (widget, event);
|
|
Packit |
1069cd |
gdk_event_free (event);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_surface (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->subcompositor && !priv->clutter_surface)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GdkDisplay *display;
|
|
Packit |
1069cd |
struct wl_compositor *compositor;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
display = gtk_widget_get_display (GTK_WIDGET (embed));
|
|
Packit |
1069cd |
compositor = gdk_wayland_display_get_wl_compositor (display);
|
|
Packit |
1069cd |
priv->clutter_surface = wl_compositor_create_surface (compositor);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_subsurface (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv;
|
|
Packit |
1069cd |
GtkWidget *widget;
|
|
Packit |
1069cd |
struct wl_surface *gtk_surface;
|
|
Packit |
1069cd |
GdkWindow *window;
|
|
Packit |
1069cd |
gint x, y;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
widget = GTK_WIDGET (embed);
|
|
Packit |
1069cd |
priv = embed->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->subsurface)
|
|
Packit |
1069cd |
return;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
window = gtk_widget_get_window (widget);
|
|
Packit |
1069cd |
gtk_surface = gdk_wayland_window_get_wl_surface (gdk_window_get_toplevel (window));
|
|
Packit |
1069cd |
priv->subsurface =
|
|
Packit |
1069cd |
wl_subcompositor_get_subsurface (priv->subcompositor,
|
|
Packit |
1069cd |
priv->clutter_surface,
|
|
Packit |
1069cd |
gtk_surface);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gdk_window_get_origin (window, &x, &y);
|
|
Packit |
1069cd |
wl_subsurface_set_position (priv->subsurface, x, y);
|
|
Packit |
1069cd |
wl_subsurface_set_desync (priv->subsurface);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_stage_realized (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (embed)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (!gtk_widget_get_realized (GTK_WIDGET (embed)))
|
|
Packit |
1069cd |
return;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (!clutter_actor_is_realized (priv->stage))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (embed));
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_GDK)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_GDK))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
clutter_gdk_set_stage_foreign (CLUTTER_STAGE (priv->stage), window);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11) &&
|
|
Packit |
1069cd |
GDK_IS_X11_WINDOW (window))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
clutter_x11_set_stage_foreign (CLUTTER_STAGE (priv->stage),
|
|
Packit |
1069cd |
GDK_WINDOW_XID (window));
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WIN32) && defined(CLUTTER_WINDOWING_WIN32)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WIN32) &&
|
|
Packit |
1069cd |
GDK_IS_WIN32_WINDOW (window))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
clutter_win32_set_stage_foreign (CLUTTER_STAGE (priv->stage),
|
|
Packit |
1069cd |
GDK_WINDOW_HWND (window));
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined (CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND) &&
|
|
Packit |
1069cd |
GDK_IS_WAYLAND_WINDOW (window))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_surface (embed);
|
|
Packit |
1069cd |
clutter_wayland_stage_set_wl_surface (CLUTTER_STAGE (priv->stage),
|
|
Packit |
1069cd |
priv->clutter_surface);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_warning ("No backend found!");
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_actor_realize (priv->stage);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* A stage cannot really be unmapped because it is the top of
|
|
Packit |
1069cd |
* Clutter's scene tree. So if the Gtk embedder is mapped, we
|
|
Packit |
1069cd |
* translate this as visible for the ClutterStage. */
|
|
Packit |
1069cd |
if (gtk_widget_get_mapped (GTK_WIDGET (embed)))
|
|
Packit |
1069cd |
clutter_actor_show (priv->stage);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_actor_queue_relayout (priv->stage);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_send_configure (embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined (CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_subsurface (embed);
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_stage_unrealize (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
g_clear_pointer (&priv->subsurface, wl_subsurface_destroy);
|
|
Packit |
1069cd |
g_clear_pointer (&priv->clutter_surface, wl_surface_destroy);
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* gtk may emit an unmap signal after dispose, so it's possible we
|
|
Packit |
1069cd |
* may have already disposed priv->stage. */
|
|
Packit |
1069cd |
if (priv->stage != NULL)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
clutter_actor_hide (priv->stage);
|
|
Packit |
1069cd |
clutter_actor_unrealize (priv->stage);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
on_stage_queue_redraw (ClutterStage *stage,
|
|
Packit |
1069cd |
ClutterActor *origin,
|
|
Packit |
1069cd |
gpointer user_data)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkWidget *embed = user_data;
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (embed)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->n_active_children > 0)
|
|
Packit |
1069cd |
priv->geometry_changed = TRUE;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_widget_queue_draw (embed);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
on_stage_queue_relayout (ClutterStage *stage,
|
|
Packit |
1069cd |
gpointer user_data)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkWidget *embed = user_data;
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (embed)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->use_layout_size)
|
|
Packit |
1069cd |
gtk_widget_queue_resize (embed);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_dispose (GObject *gobject)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (gobject)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->stage)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
if (priv->queue_redraw_id)
|
|
Packit |
1069cd |
g_signal_handler_disconnect (priv->stage, priv->queue_redraw_id);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->queue_relayout_id)
|
|
Packit |
1069cd |
g_signal_handler_disconnect (priv->stage, priv->queue_relayout_id);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
priv->queue_redraw_id = 0;
|
|
Packit |
1069cd |
priv->queue_relayout_id = 0;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_actor_destroy (priv->stage);
|
|
Packit |
1069cd |
priv->stage = NULL;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
g_clear_pointer (&priv->subsurface, wl_subsurface_destroy);
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
G_OBJECT_CLASS (gtk_clutter_embed_parent_class)->dispose (gobject);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_show (GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->show (widget);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_stage_realized (GTK_CLUTTER_EMBED (widget));
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static GdkWindow *
|
|
Packit |
1069cd |
pick_embedded_child (GdkWindow *offscreen_window,
|
|
Packit |
1069cd |
double widget_x,
|
|
Packit |
1069cd |
double widget_y,
|
|
Packit |
1069cd |
GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
ClutterActor *a;
|
|
Packit |
1069cd |
GtkWidget *widget;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
a = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (priv->stage),
|
|
Packit |
1069cd |
CLUTTER_PICK_REACTIVE,
|
|
Packit |
1069cd |
widget_x, widget_y);
|
|
Packit |
1069cd |
if (GTK_CLUTTER_IS_ACTOR (a))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
widget = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (a));
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (GTK_CLUTTER_OFFSCREEN (widget)->active)
|
|
Packit |
1069cd |
return gtk_widget_get_window (widget);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return NULL;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static GdkFilterReturn
|
|
Packit |
1069cd |
gtk_clutter_filter_func (GdkXEvent *native_event,
|
|
Packit |
1069cd |
GdkEvent *event G_GNUC_UNUSED,
|
|
Packit |
1069cd |
gpointer user_data G_GNUC_UNUSED)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
XEvent *xevent = native_event;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* let Clutter handle all events coming from the windowing system */
|
|
Packit |
1069cd |
clutter_x11_handle_event (xevent);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_WIN32)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WIN32))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
MSG *msg = native_event;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_win32_handle_event (msg);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
g_critical ("Unsuppored Clutter backend");
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* we don't care if Clutter handled the event: we want GDK to continue
|
|
Packit |
1069cd |
* the event processing as usual
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
return GDK_FILTER_CONTINUE;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_draw (GtkWidget *widget, cairo_t *cr)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_GDK)
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_GDK))
|
|
Packit |
1069cd |
clutter_stage_ensure_redraw (CLUTTER_STAGE (priv->stage));
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->draw (widget, cr);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_realize (GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkAllocation allocation;
|
|
Packit |
1069cd |
GtkStyleContext *style_context;
|
|
Packit |
1069cd |
GdkWindow *window;
|
|
Packit |
1069cd |
GdkWindowAttr attributes;
|
|
Packit |
1069cd |
gint attributes_mask;
|
|
Packit |
1069cd |
gint border_width;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_GDK)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_GDK))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GdkVisual *visual = clutter_gdk_get_visual ();
|
|
Packit |
1069cd |
gtk_widget_set_visual (widget, visual);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
const XVisualInfo *xvinfo;
|
|
Packit |
1069cd |
GdkVisual *visual;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* We need to use the colormap from the Clutter visual, since
|
|
Packit |
1069cd |
* the visual is tied to the GLX context
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
xvinfo = clutter_x11_get_visual_info ();
|
|
Packit |
1069cd |
if (xvinfo == None)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_critical ("Unable to retrieve the XVisualInfo from Clutter");
|
|
Packit |
1069cd |
return;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
visual = gdk_x11_screen_lookup_visual (gtk_widget_get_screen (widget),
|
|
Packit |
1069cd |
xvinfo->visualid);
|
|
Packit |
1069cd |
gtk_widget_set_visual (widget, visual);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_widget_set_realized (widget, TRUE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_widget_get_allocation (widget, &allocation);
|
|
Packit |
1069cd |
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
attributes.window_type = GDK_WINDOW_CHILD;
|
|
Packit |
1069cd |
attributes.x = allocation.x + border_width;
|
|
Packit |
1069cd |
attributes.y = allocation.y + border_width;
|
|
Packit |
1069cd |
attributes.width = allocation.width - 2 * border_width;
|
|
Packit |
1069cd |
attributes.height = allocation.height - 2 * border_width;
|
|
Packit |
1069cd |
attributes.wclass = GDK_INPUT_OUTPUT;
|
|
Packit |
1069cd |
attributes.visual = gtk_widget_get_visual (widget);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* NOTE: GDK_MOTION_NOTIFY above should be safe as Clutter does its own
|
|
Packit |
1069cd |
* throttling.
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
attributes.event_mask = gtk_widget_get_events (widget)
|
|
Packit |
1069cd |
| GDK_EXPOSURE_MASK
|
|
Packit |
1069cd |
| GDK_SCROLL_MASK
|
|
Packit |
1069cd |
| GDK_BUTTON_PRESS_MASK
|
|
Packit |
1069cd |
| GDK_BUTTON_RELEASE_MASK
|
|
Packit |
1069cd |
| GDK_KEY_PRESS_MASK
|
|
Packit |
1069cd |
| GDK_KEY_RELEASE_MASK
|
|
Packit |
1069cd |
| GDK_POINTER_MOTION_MASK
|
|
Packit |
1069cd |
| GDK_ENTER_NOTIFY_MASK
|
|
Packit |
1069cd |
| GDK_LEAVE_NOTIFY_MASK
|
|
Packit |
1069cd |
| GDK_TOUCH_MASK
|
|
Packit |
1069cd |
| GDK_SMOOTH_SCROLL_MASK
|
|
Packit |
1069cd |
| GDK_STRUCTURE_MASK;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
window = gdk_window_new (gtk_widget_get_parent_window (widget),
|
|
Packit |
1069cd |
&attributes,
|
|
Packit |
1069cd |
attributes_mask);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_widget_set_window (widget, window);
|
|
Packit |
1069cd |
gdk_window_set_user_data (window, widget);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* this does the translation of the event from Clutter to GDK
|
|
Packit |
1069cd |
* we embedding a GtkWidget inside a GtkClutterActor
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
g_signal_connect (window, "pick-embedded-child",
|
|
Packit |
1069cd |
G_CALLBACK (pick_embedded_child),
|
|
Packit |
1069cd |
widget);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
style_context = gtk_widget_get_style_context (widget);
|
|
Packit |
1069cd |
gtk_style_context_set_background (style_context, window);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11) &&
|
|
Packit |
1069cd |
GDK_IS_X11_WINDOW (window))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
if (num_filter == 0)
|
|
Packit |
1069cd |
gdk_window_add_filter (NULL, gtk_clutter_filter_func, widget);
|
|
Packit |
1069cd |
num_filter++;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WIN32) && defined(CLUTTER_WINDOWING_WIN32)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WIN32) &&
|
|
Packit |
1069cd |
GDK_IS_WIN32_WINDOW (window))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
if (num_filter == 0)
|
|
Packit |
1069cd |
gdk_window_add_filter (NULL, gtk_clutter_filter_func, widget);
|
|
Packit |
1069cd |
num_filter++;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
/* Nothing to do. */
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_stage_realized (GTK_CLUTTER_EMBED (widget));
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_unrealize (GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (widget);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (num_filter > 0)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
num_filter--;
|
|
Packit |
1069cd |
if (num_filter == 0)
|
|
Packit |
1069cd |
gdk_window_remove_filter (NULL, gtk_clutter_filter_func, widget);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_stage_unrealize (embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->unrealize (widget);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static GtkSizeRequestMode
|
|
Packit |
1069cd |
gtk_clutter_embed_get_request_mode (GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
GtkSizeRequestMode mode;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
|
|
Packit |
1069cd |
if (priv->stage != NULL &&
|
|
Packit |
1069cd |
priv->use_layout_size &&
|
|
Packit |
1069cd |
clutter_actor_get_layout_manager (priv->stage) != NULL)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
switch (clutter_actor_get_request_mode (priv->stage))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
case CLUTTER_REQUEST_HEIGHT_FOR_WIDTH:
|
|
Packit |
1069cd |
mode = GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
case CLUTTER_REQUEST_WIDTH_FOR_HEIGHT:
|
|
Packit |
1069cd |
mode = GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
case CLUTTER_REQUEST_CONTENT_SIZE:
|
|
Packit |
1069cd |
mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return mode;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_get_preferred_width_for_height (GtkWidget *widget,
|
|
Packit |
1069cd |
gint height,
|
|
Packit |
1069cd |
gint *minimum,
|
|
Packit |
1069cd |
gint *natural)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
float min, nat;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
min = 0;
|
|
Packit |
1069cd |
nat = 0;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->stage != NULL &&
|
|
Packit |
1069cd |
priv->use_layout_size)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
ClutterLayoutManager *manager = clutter_actor_get_layout_manager (priv->stage);
|
|
Packit |
1069cd |
if (manager)
|
|
Packit |
1069cd |
clutter_layout_manager_get_preferred_width (manager,
|
|
Packit |
1069cd |
CLUTTER_CONTAINER (priv->stage),
|
|
Packit |
1069cd |
(float)height, &min, &nat);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
min = ceilf (min);
|
|
Packit |
1069cd |
nat = ceilf (nat);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (minimum)
|
|
Packit |
1069cd |
*minimum = min;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (natural)
|
|
Packit |
1069cd |
*natural = nat;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_get_preferred_height_for_width (GtkWidget *widget,
|
|
Packit |
1069cd |
gint width,
|
|
Packit |
1069cd |
gint *minimum,
|
|
Packit |
1069cd |
gint *natural)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
float min, nat;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
min = 0;
|
|
Packit |
1069cd |
nat = 0;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (priv->stage != NULL &&
|
|
Packit |
1069cd |
priv->use_layout_size)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
ClutterLayoutManager *manager = clutter_actor_get_layout_manager (priv->stage);
|
|
Packit |
1069cd |
if (manager)
|
|
Packit |
1069cd |
clutter_layout_manager_get_preferred_height (manager,
|
|
Packit |
1069cd |
CLUTTER_CONTAINER (priv->stage),
|
|
Packit |
1069cd |
(float)width, &min, &nat);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
min = ceilf (min);
|
|
Packit |
1069cd |
nat = ceilf (nat);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (minimum)
|
|
Packit |
1069cd |
*minimum = min;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (natural)
|
|
Packit |
1069cd |
*natural = nat;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_get_preferred_width (GtkWidget *widget,
|
|
Packit |
1069cd |
gint *minimum,
|
|
Packit |
1069cd |
gint *natural)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
gtk_clutter_embed_get_preferred_width_for_height (widget, -1, minimum, natural);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_get_preferred_height (GtkWidget *widget,
|
|
Packit |
1069cd |
gint *minimum,
|
|
Packit |
1069cd |
gint *natural)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
gtk_clutter_embed_get_preferred_height_for_width (widget, -1, minimum, natural);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_size_allocate (GtkWidget *widget,
|
|
Packit |
1069cd |
GtkAllocation *allocation)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
int scale_factor = gtk_widget_get_scale_factor (widget);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_widget_set_allocation (widget, allocation);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* change the size of the stage and ensure that the viewport
|
|
Packit |
1069cd |
* has been updated as well
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
clutter_actor_set_size (priv->stage, allocation->width, allocation->height);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (gtk_widget_get_realized (widget))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
gdk_window_move_resize (gtk_widget_get_window (widget),
|
|
Packit |
1069cd |
allocation->x,
|
|
Packit |
1069cd |
allocation->y,
|
|
Packit |
1069cd |
allocation->width,
|
|
Packit |
1069cd |
allocation->height);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_stage_ensure_viewport (CLUTTER_STAGE (priv->stage));
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_send_configure (GTK_CLUTTER_EMBED (widget));
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11) &&
|
|
Packit |
1069cd |
GDK_IS_X11_WINDOW (gtk_widget_get_window (widget)))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
XConfigureEvent xevent = { ConfigureNotify };
|
|
Packit |
1069cd |
xevent.window = GDK_WINDOW_XID (gtk_widget_get_window (widget));
|
|
Packit |
1069cd |
xevent.width = allocation->width * scale_factor;
|
|
Packit |
1069cd |
xevent.height = allocation->height * scale_factor;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* Ensure cogl knows about the new size immediately, as we will
|
|
Packit |
1069cd |
draw before we get the ConfigureNotify response. */
|
|
Packit |
1069cd |
clutter_x11_handle_event ((XEvent *)&xevent);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
if (priv->subsurface)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
gint x, y;
|
|
Packit |
1069cd |
gdk_window_get_origin (gtk_widget_get_window (widget), &x, &y);
|
|
Packit |
1069cd |
wl_subsurface_set_position (priv->subsurface, x, y);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_map_event (GtkWidget *widget,
|
|
Packit |
1069cd |
GdkEventAny *event)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (widget);
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
GtkWidgetClass *parent_class;
|
|
Packit |
1069cd |
gboolean res = FALSE;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
parent_class = GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class);
|
|
Packit |
1069cd |
if (parent_class->map_event)
|
|
Packit |
1069cd |
res = parent_class->map_event (widget, event);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_ensure_stage_realized (embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_actor_queue_redraw (priv->stage);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return res;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_unmap_event (GtkWidget *widget,
|
|
Packit |
1069cd |
GdkEventAny *event)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (widget);
|
|
Packit |
1069cd |
GtkWidgetClass *parent_class;
|
|
Packit |
1069cd |
gboolean res = FALSE;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
parent_class = GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class);
|
|
Packit |
1069cd |
if (parent_class->unmap_event)
|
|
Packit |
1069cd |
res = parent_class->unmap_event (widget, event);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_clutter_embed_stage_unrealize (embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return res;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_focus_in (GtkWidget *widget,
|
|
Packit |
1069cd |
GdkEventFocus *event)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
g_signal_emit_by_name (priv->stage, "activate");
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_stage_set_key_focus (CLUTTER_STAGE (priv->stage), NULL);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return FALSE;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_focus_out (GtkWidget *widget,
|
|
Packit |
1069cd |
GdkEventFocus *event)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
g_signal_emit_by_name (priv->stage, "deactivate");
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* give back key focus to the stage */
|
|
Packit |
1069cd |
clutter_stage_set_key_focus (CLUTTER_STAGE (priv->stage), NULL);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return FALSE;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_key_event (GtkWidget *widget,
|
|
Packit |
1069cd |
GdkEventKey *event)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
ClutterDeviceManager *manager;
|
|
Packit |
1069cd |
ClutterInputDevice *device;
|
|
Packit |
1069cd |
ClutterEvent cevent = { 0, };
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (event->type == GDK_KEY_PRESS)
|
|
Packit |
1069cd |
cevent.key.type = CLUTTER_KEY_PRESS;
|
|
Packit |
1069cd |
else if (event->type == GDK_KEY_RELEASE)
|
|
Packit |
1069cd |
cevent.key.type = CLUTTER_KEY_RELEASE;
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
return FALSE;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
manager = clutter_device_manager_get_default ();
|
|
Packit |
1069cd |
device = clutter_device_manager_get_core_device (manager, CLUTTER_KEYBOARD_DEVICE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
cevent.key.stage = CLUTTER_STAGE (priv->stage);
|
|
Packit |
1069cd |
cevent.key.time = event->time;
|
|
Packit |
1069cd |
cevent.key.modifier_state = event->state;
|
|
Packit |
1069cd |
cevent.key.keyval = event->keyval;
|
|
Packit |
1069cd |
cevent.key.hardware_keycode = event->hardware_keycode;
|
|
Packit |
1069cd |
cevent.key.unicode_value = gdk_keyval_to_unicode (event->keyval);
|
|
Packit |
1069cd |
cevent.key.device = device;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
clutter_do_event (&cevent);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return FALSE;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_style_updated (GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GdkScreen *screen;
|
|
Packit |
1069cd |
GtkSettings *gtk_settings;
|
|
Packit |
1069cd |
ClutterSettings *clutter_settings;
|
|
Packit |
1069cd |
gchar *font_name;
|
|
Packit |
1069cd |
gint double_click_time, double_click_distance;
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
gint xft_dpi, xft_hinting, xft_antialias;
|
|
Packit |
1069cd |
gchar *xft_hintstyle, *xft_rgba;
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (gtk_widget_get_realized (widget))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
#if 0
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv;
|
|
Packit |
1069cd |
GtkStyleContext *style_context;
|
|
Packit |
1069cd |
GtkStateFlags state_flags;
|
|
Packit |
1069cd |
GdkRGBA *bg_color;
|
|
Packit |
1069cd |
ClutterColor color;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
style_context = gtk_widget_get_style_context (widget);
|
|
Packit |
1069cd |
state_flags = gtk_widget_get_state_flags (widget);
|
|
Packit |
1069cd |
gtk_style_context_get (style_context, state_flags,
|
|
Packit |
1069cd |
"background-color", &bg_color,
|
|
Packit |
1069cd |
NULL);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
color.red = CLAMP (bg_color->red * 255, 0, 255);
|
|
Packit |
1069cd |
color.green = CLAMP (bg_color->green * 255, 0, 255);
|
|
Packit |
1069cd |
color.blue = CLAMP (bg_color->blue * 255, 0, 255);
|
|
Packit |
1069cd |
color.alpha = CLAMP (bg_color->alpha * 255, 0, 255);
|
|
Packit |
1069cd |
clutter_stage_set_color (CLUTTER_STAGE (priv->stage), &color;;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gdk_rgba_free (bg_color);
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (gtk_widget_has_screen (widget))
|
|
Packit |
1069cd |
screen = gtk_widget_get_screen (widget);
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
screen = gdk_screen_get_default ();
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gtk_settings = gtk_settings_get_for_screen (screen);
|
|
Packit |
1069cd |
g_object_get (G_OBJECT (gtk_settings),
|
|
Packit |
1069cd |
"gtk-font-name", &font_name,
|
|
Packit |
1069cd |
"gtk-double-click-time", &double_click_time,
|
|
Packit |
1069cd |
"gtk-double-click-distance", &double_click_distance,
|
|
Packit |
1069cd |
NULL);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (GDK_IS_X11_SCREEN (screen))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_object_get (G_OBJECT (gtk_settings),
|
|
Packit |
1069cd |
"gtk-xft-dpi", &xft_dpi,
|
|
Packit |
1069cd |
"gtk-xft-antialias", &xft_antialias,
|
|
Packit |
1069cd |
"gtk-xft-hinting", &xft_hinting,
|
|
Packit |
1069cd |
"gtk-xft-hintstyle", &xft_hintstyle,
|
|
Packit |
1069cd |
"gtk-xft-rgba", &xft_rgba,
|
|
Packit |
1069cd |
NULL);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* copy all settings and values coming from GTK+ into
|
|
Packit |
1069cd |
* the ClutterBackend; this way, a scene embedded into
|
|
Packit |
1069cd |
* a GtkClutterEmbed will not look completely alien
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
clutter_settings = clutter_settings_get_default ();
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (GDK_IS_X11_SCREEN (screen))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_object_set (G_OBJECT (clutter_settings),
|
|
Packit |
1069cd |
"font-name", font_name,
|
|
Packit |
1069cd |
"double-click-time", double_click_time,
|
|
Packit |
1069cd |
"double-click-distance", double_click_distance,
|
|
Packit |
1069cd |
"font-antialias", xft_antialias,
|
|
Packit |
1069cd |
"font-dpi", xft_dpi,
|
|
Packit |
1069cd |
"font-hinting", xft_hinting,
|
|
Packit |
1069cd |
"font-hint-style", xft_hintstyle,
|
|
Packit |
1069cd |
"font-subpixel-order", xft_rgba,
|
|
Packit |
1069cd |
NULL);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_object_set (G_OBJECT (clutter_settings),
|
|
Packit |
1069cd |
"font-name", font_name,
|
|
Packit |
1069cd |
"double-click-time", double_click_time,
|
|
Packit |
1069cd |
"double-click-distance", double_click_distance,
|
|
Packit |
1069cd |
NULL);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_X11) && defined(CLUTTER_WINDOWING_X11)
|
|
Packit |
1069cd |
if (GDK_IS_X11_SCREEN (screen))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_free (xft_hintstyle);
|
|
Packit |
1069cd |
g_free (xft_rgba);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
g_free (font_name);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->style_updated (widget);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
void
|
|
Packit |
1069cd |
_gtk_clutter_embed_set_child_active (GtkClutterEmbed *embed,
|
|
Packit |
1069cd |
GtkWidget *child,
|
|
Packit |
1069cd |
gboolean active)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GdkWindow *child_window;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
child_window = gtk_widget_get_window (child);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (active)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
embed->priv->n_active_children++;
|
|
Packit |
1069cd |
gdk_offscreen_window_set_embedder (child_window,
|
|
Packit |
1069cd |
gtk_widget_get_window (GTK_WIDGET (embed)));
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
else
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
embed->priv->n_active_children--;
|
|
Packit |
1069cd |
gdk_offscreen_window_set_embedder (child_window,
|
|
Packit |
1069cd |
NULL);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_add (GtkContainer *container,
|
|
Packit |
1069cd |
GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (container)->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#ifndef G_DISABLE_ASSERT
|
|
Packit |
1069cd |
if (G_UNLIKELY (!GTK_CLUTTER_IS_OFFSCREEN (widget)))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_critical ("Widgets of type '%s' do not support children.",
|
|
Packit |
1069cd |
G_OBJECT_TYPE_NAME (container));
|
|
Packit |
1069cd |
return;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
priv->children = g_list_prepend (priv->children, widget);
|
|
Packit |
1069cd |
gtk_widget_set_parent (widget, GTK_WIDGET (container));
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_remove (GtkContainer *container,
|
|
Packit |
1069cd |
GtkWidget *widget)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (container)->priv;
|
|
Packit |
1069cd |
GList *l;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
l = g_list_find (priv->children, widget);
|
|
Packit |
1069cd |
if (l != NULL)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
priv->children = g_list_delete_link (priv->children, l);
|
|
Packit |
1069cd |
gtk_widget_unparent (widget);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_forall (GtkContainer *container,
|
|
Packit |
1069cd |
gboolean include_internals,
|
|
Packit |
1069cd |
GtkCallback callback,
|
|
Packit |
1069cd |
gpointer callback_data)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (container)->priv;
|
|
Packit |
1069cd |
GList *l;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (include_internals)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
for (l = priv->children; l != NULL; l = l->next)
|
|
Packit |
1069cd |
callback (l->data, callback_data);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static GType
|
|
Packit |
1069cd |
gtk_clutter_embed_child_type (GtkContainer *container)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
/* we only accept GtkClutterOffscreen children */
|
|
Packit |
1069cd |
return GTK_CLUTTER_TYPE_OFFSCREEN;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_event (GtkWidget *widget,
|
|
Packit |
1069cd |
GdkEvent *event)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
#if defined(CLUTTER_WINDOWING_GDK)
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_GDK))
|
|
Packit |
1069cd |
clutter_gdk_handle_event (event);
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return FALSE;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_set_property (GObject *gobject,
|
|
Packit |
1069cd |
guint prop_id,
|
|
Packit |
1069cd |
const GValue *value,
|
|
Packit |
1069cd |
GParamSpec *pspec)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (gobject);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
switch (prop_id)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
case PROP_USE_LAYOUT_SIZE:
|
|
Packit |
1069cd |
gtk_clutter_embed_set_use_layout_size (embed, g_value_get_boolean (value));
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
default:
|
|
Packit |
1069cd |
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_get_property (GObject *gobject,
|
|
Packit |
1069cd |
guint prop_id,
|
|
Packit |
1069cd |
GValue *value,
|
|
Packit |
1069cd |
GParamSpec *pspec)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (gobject);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
switch (prop_id)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
case PROP_USE_LAYOUT_SIZE:
|
|
Packit |
1069cd |
g_value_set_boolean (value, embed->priv->use_layout_size);
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
default:
|
|
Packit |
1069cd |
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
Packit |
1069cd |
break;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_class_init (GtkClutterEmbedClass *klass)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
1069cd |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
Packit |
1069cd |
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
|
|
Packit |
1069cd |
GParamSpec *pspec;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gobject_class->dispose = gtk_clutter_embed_dispose;
|
|
Packit |
1069cd |
gobject_class->set_property = gtk_clutter_embed_set_property;
|
|
Packit |
1069cd |
gobject_class->get_property = gtk_clutter_embed_get_property;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
widget_class->style_updated = gtk_clutter_embed_style_updated;
|
|
Packit |
1069cd |
widget_class->size_allocate = gtk_clutter_embed_size_allocate;
|
|
Packit |
1069cd |
widget_class->draw = gtk_clutter_embed_draw;
|
|
Packit |
1069cd |
widget_class->realize = gtk_clutter_embed_realize;
|
|
Packit |
1069cd |
widget_class->unrealize = gtk_clutter_embed_unrealize;
|
|
Packit |
1069cd |
widget_class->show = gtk_clutter_embed_show;
|
|
Packit |
1069cd |
widget_class->map_event = gtk_clutter_embed_map_event;
|
|
Packit |
1069cd |
widget_class->unmap_event = gtk_clutter_embed_unmap_event;
|
|
Packit |
1069cd |
widget_class->focus_in_event = gtk_clutter_embed_focus_in;
|
|
Packit |
1069cd |
widget_class->focus_out_event = gtk_clutter_embed_focus_out;
|
|
Packit |
1069cd |
widget_class->key_press_event = gtk_clutter_embed_key_event;
|
|
Packit |
1069cd |
widget_class->key_release_event = gtk_clutter_embed_key_event;
|
|
Packit |
1069cd |
widget_class->event = gtk_clutter_embed_event;
|
|
Packit |
1069cd |
widget_class->get_request_mode = gtk_clutter_embed_get_request_mode;
|
|
Packit |
1069cd |
widget_class->get_preferred_width = gtk_clutter_embed_get_preferred_width;
|
|
Packit |
1069cd |
widget_class->get_preferred_height = gtk_clutter_embed_get_preferred_height;
|
|
Packit |
1069cd |
widget_class->get_preferred_width_for_height = gtk_clutter_embed_get_preferred_width_for_height;
|
|
Packit |
1069cd |
widget_class->get_preferred_height_for_width = gtk_clutter_embed_get_preferred_height_for_width;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
container_class->add = gtk_clutter_embed_add;
|
|
Packit |
1069cd |
container_class->remove = gtk_clutter_embed_remove;
|
|
Packit |
1069cd |
container_class->forall = gtk_clutter_embed_forall;
|
|
Packit |
1069cd |
container_class->child_type = gtk_clutter_embed_child_type;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/**
|
|
Packit |
1069cd |
* GtkClutterEmbed:use-layout-size:
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* The #GtkWidget to be embedded into the #GtkClutterActor
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Since: 1.4
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
pspec = g_param_spec_boolean ("use-layout-size",
|
|
Packit |
1069cd |
"Use layout size",
|
|
Packit |
1069cd |
"Whether to use the reported size of the LayoutManager on the stage as the widget size.",
|
|
Packit |
1069cd |
FALSE,
|
|
Packit |
1069cd |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
|
|
Packit |
1069cd |
g_object_class_install_property (gobject_class, PROP_USE_LAYOUT_SIZE, pspec);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
registry_handle_global (void *data,
|
|
Packit |
1069cd |
struct wl_registry *registry,
|
|
Packit |
1069cd |
uint32_t name,
|
|
Packit |
1069cd |
const char *interface,
|
|
Packit |
1069cd |
uint32_t version)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbed *embed = data;
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
if (strcmp (interface, "wl_subcompositor") == 0)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
priv->subcompositor = wl_registry_bind (registry,
|
|
Packit |
1069cd |
name,
|
|
Packit |
1069cd |
&wl_subcompositor_interface,
|
|
Packit |
1069cd |
1);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
registry_handle_global_remove (void *data,
|
|
Packit |
1069cd |
struct wl_registry *registry,
|
|
Packit |
1069cd |
uint32_t name)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static const struct wl_registry_listener registry_listener = {
|
|
Packit |
1069cd |
registry_handle_global,
|
|
Packit |
1069cd |
registry_handle_global_remove
|
|
Packit |
1069cd |
};
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
static void
|
|
Packit |
1069cd |
gtk_clutter_embed_init (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv;
|
|
Packit |
1069cd |
GtkWidget *widget;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
embed->priv = priv = gtk_clutter_embed_get_instance_private (embed);
|
|
Packit |
1069cd |
widget = GTK_WIDGET (embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* we have a real window backing our drawing */
|
|
Packit |
1069cd |
gtk_widget_set_has_window (widget, TRUE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* we accept key focus */
|
|
Packit |
1069cd |
gtk_widget_set_can_focus (widget, TRUE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* we own the whole drawing of this widget, including the background */
|
|
Packit |
1069cd |
gtk_widget_set_app_paintable (widget, TRUE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* this widget should expand in both directions */
|
|
Packit |
1069cd |
gtk_widget_set_hexpand (widget, TRUE);
|
|
Packit |
1069cd |
gtk_widget_set_vexpand (widget, TRUE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* we always create new stages rather than use the default */
|
|
Packit |
1069cd |
priv->stage = clutter_stage_new ();
|
|
Packit |
1069cd |
g_object_set_data (G_OBJECT (priv->stage),
|
|
Packit |
1069cd |
"gtk-clutter-embed",
|
|
Packit |
1069cd |
embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* intercept the queue-redraw signal of the stage to know when
|
|
Packit |
1069cd |
* Clutter-side requests a redraw; this way we can also request
|
|
Packit |
1069cd |
* a redraw GTK-side
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
priv->queue_redraw_id =
|
|
Packit |
1069cd |
g_signal_connect (priv->stage,
|
|
Packit |
1069cd |
"queue-redraw", G_CALLBACK (on_stage_queue_redraw),
|
|
Packit |
1069cd |
embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/* intercept the queue-relayout signal of the stage to know when
|
|
Packit |
1069cd |
* Clutter-side needs to renegotiate it's size; this way we can
|
|
Packit |
1069cd |
* also request a resize GTK-side
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
priv->queue_relayout_id =
|
|
Packit |
1069cd |
g_signal_connect (priv->stage,
|
|
Packit |
1069cd |
"queue-relayout", G_CALLBACK (on_stage_queue_relayout),
|
|
Packit |
1069cd |
embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
#if defined(GDK_WINDOWING_WAYLAND) && defined(CLUTTER_WINDOWING_WAYLAND)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GdkDisplay *gdk_display = gtk_widget_get_display (widget);
|
|
Packit |
1069cd |
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND) &&
|
|
Packit |
1069cd |
GDK_IS_WAYLAND_DISPLAY (gdk_display))
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
struct wl_display *display;
|
|
Packit |
1069cd |
struct wl_registry *registry;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
display = gdk_wayland_display_get_wl_display (gdk_display);
|
|
Packit |
1069cd |
registry = wl_display_get_registry (display);
|
|
Packit |
1069cd |
wl_registry_add_listener (registry, ®istry_listener, embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
wl_display_roundtrip (display);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
#endif
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/**
|
|
Packit |
1069cd |
* gtk_clutter_embed_new:
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Creates a new #GtkClutterEmbed widget. This widget can be
|
|
Packit |
1069cd |
* used to build a scene using Clutter API into a GTK+ application.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Return value: the newly created #GtkClutterEmbed
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
GtkWidget *
|
|
Packit |
1069cd |
gtk_clutter_embed_new (void)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
return g_object_new (GTK_CLUTTER_TYPE_EMBED, NULL);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/**
|
|
Packit |
1069cd |
* gtk_clutter_embed_get_stage:
|
|
Packit |
1069cd |
* @embed: a #GtkClutterEmbed
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Retrieves the #ClutterStage from @embed. The returned stage can be
|
|
Packit |
1069cd |
* used to add actors to the Clutter scene.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Return value: (transfer none): the Clutter stage. You should never
|
|
Packit |
1069cd |
* destroy or unref the returned actor.
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
ClutterActor *
|
|
Packit |
1069cd |
gtk_clutter_embed_get_stage (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
g_return_val_if_fail (GTK_CLUTTER_IS_EMBED (embed), NULL);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return embed->priv->stage;
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/**
|
|
Packit |
1069cd |
* gtk_clutter_embed_set_use_layout_size:
|
|
Packit |
1069cd |
* @embed: a #GtkClutterEmbed
|
|
Packit |
1069cd |
* @use_layout_size: a boolean
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Changes the way @embed requests size. If @use_layout_size is
|
|
Packit |
1069cd |
* %TRUE, the @embed widget will request the size that the
|
|
Packit |
1069cd |
* LayoutManager reports as the preferred size. This means that
|
|
Packit |
1069cd |
* a Gtk+ window will automatically get the natural and minimum
|
|
Packit |
1069cd |
* toplevel window sizes. This is useful when the contents of the
|
|
Packit |
1069cd |
* clutter stage is similar to a traditional UI.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* If @use_layout_size is %FALSE (which is the default) then @embed
|
|
Packit |
1069cd |
* will not request any size and its up to the embedder to make sure
|
|
Packit |
1069cd |
* there is some size (by setting a custom size on the widget or a default
|
|
Packit |
1069cd |
* size on the toplevel. This makes more sense when using the @embed
|
|
Packit |
1069cd |
* as a viewport into a potentially unlimited clutter space.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Since: 1.4
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
void
|
|
Packit |
1069cd |
gtk_clutter_embed_set_use_layout_size (GtkClutterEmbed *embed,
|
|
Packit |
1069cd |
gboolean use_layout_size)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
g_return_if_fail (GTK_CLUTTER_IS_EMBED (embed));
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
use_layout_size = !!use_layout_size;
|
|
Packit |
1069cd |
if (use_layout_size != priv->use_layout_size)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
priv->use_layout_size = use_layout_size;
|
|
Packit |
1069cd |
gtk_widget_queue_resize (GTK_WIDGET (embed));
|
|
Packit |
1069cd |
g_object_notify (G_OBJECT (embed), "use-layout-size");
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
extern gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_get_honor_stage_size (GtkClutterEmbed *embed);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_get_honor_stage_size (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
return gtk_clutter_embed_get_use_layout_size (embed);
|
|
Packit |
1069cd |
}
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
/**
|
|
Packit |
1069cd |
* gtk_clutter_embed_get_use_layout_size:
|
|
Packit |
1069cd |
* @embed: a #GtkClutterEmbed
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Retrieves whether the embedding uses the layout size, see
|
|
Packit |
1069cd |
* gtk_clutter_embed_set_use_layout_size() for details.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Return value: %TRUE if reporting stage size as widget size, %FALSE otherwise.
|
|
Packit |
1069cd |
*
|
|
Packit |
1069cd |
* Since: 1.4
|
|
Packit |
1069cd |
*/
|
|
Packit |
1069cd |
gboolean
|
|
Packit |
1069cd |
gtk_clutter_embed_get_use_layout_size (GtkClutterEmbed *embed)
|
|
Packit |
1069cd |
{
|
|
Packit |
1069cd |
GtkClutterEmbedPrivate *priv = embed->priv;
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
g_return_val_if_fail (GTK_CLUTTER_IS_EMBED (embed), FALSE);
|
|
Packit |
1069cd |
|
|
Packit |
1069cd |
return priv->use_layout_size;
|
|
Packit |
1069cd |
}
|