gdk: drop gdk backend

This commit is contained in:
Ray Strode 2016-01-12 12:04:41 -05:00 committed by Rui Matos
parent 0777de1757
commit 04c84b049f
19 changed files with 1 additions and 3468 deletions

View File

@ -491,45 +491,6 @@ compat_libs += \
$(NULL)
endif
# GDK backend rules
gdk_source_c = \
gdk/clutter-backend-gdk.c \
gdk/clutter-device-manager-gdk.c \
gdk/clutter-event-gdk.c \
gdk/clutter-input-device-gdk.c \
gdk/clutter-master-clock-gdk.c \
gdk/clutter-stage-gdk.c \
$(NULL)
gdk_source_h = \
gdk/clutter-gdk.h \
$(NULL)
gdk_source_h_priv = \
gdk/clutter-settings-gdk.h \
gdk/clutter-backend-gdk.h \
gdk/clutter-device-manager-gdk.h \
gdk/clutter-input-device-gdk.h \
gdk/clutter-master-clock-gdk.h \
gdk/clutter-stage-gdk.h \
$(NULL)
if SUPPORT_GDK
backend_source_h += $(gdk_source_h)
backend_source_c += $(gdk_source_c)
backend_source_h_priv += $(gdk_source_h_priv)
cluttergdk_includedir = $(clutter_includedir)/gdk
cluttergdk_include_HEADERS = $(gdk_source_h)
clutter-gdk-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc
$(QUIET_GEN)cp -f $< $(@F)
pc_files += clutter-gdk-$(CLUTTER_API_VERSION).pc
gdk_introspection = $(gdk_source_c) $(gdk_source_h)
endif # SUPPORT_GDK
egl_tslib_h = tslib/clutter-event-tslib.h
egl_tslib_c = tslib/clutter-event-tslib.c
@ -801,23 +762,6 @@ ClutterX11_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \
INTROSPECTION_GIRS += ClutterX11-@CLUTTER_API_VERSION@.gir
endif # SUPPORT_X11
if SUPPORT_GDK
ClutterGdk-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir
ClutterGdk_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = ClutterGdk
ClutterGdk_@CLUTTER_API_VERSION_AM@_gir_INCLUDES = Gdk-3.0
ClutterGdk_@CLUTTER_API_VERSION_AM@_gir_LIBS = libclutter-@CLUTTER_API_VERSION@.la
ClutterGdk_@CLUTTER_API_VERSION_AM@_gir_FILES = $(gdk_introspection)
ClutterGdk_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
ClutterGdk_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \
--warn-all \
--c-include='clutter/gdk/clutter-gdk.h' \
--pkg-export=clutter-gdk-@CLUTTER_API_VERSION@ \
--include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir
INTROSPECTION_GIRS += ClutterGdk-@CLUTTER_API_VERSION@.gir
endif # SUPPORT_GDK
# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to
# install anything - we need to install inside our prefix.
girdir = $(datadir)/gir-1.0

View File

@ -67,9 +67,6 @@
#ifdef CLUTTER_INPUT_X11
#include "x11/clutter-backend-x11.h"
#endif
#ifdef CLUTTER_INPUT_GDK
#include "gdk/clutter-backend-gdk.h"
#endif
#ifdef CLUTTER_INPUT_EVDEV
#include "evdev/clutter-device-manager-evdev.h"
#endif
@ -524,9 +521,6 @@ static const struct {
const char *name;
ClutterBackend * (* create_backend) (void);
} available_backends[] = {
#ifdef CLUTTER_WINDOWING_GDK
{ CLUTTER_WINDOWING_GDK, clutter_backend_gdk_new },
#endif
#ifdef CLUTTER_WINDOWING_X11
{ CLUTTER_WINDOWING_X11, clutter_backend_x11_new },
#endif
@ -605,14 +599,6 @@ clutter_backend_real_init_events (ClutterBackend *backend)
}
else
#endif
#ifdef CLUTTER_INPUT_GDK
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_GDK) &&
(input_backend == NULL || input_backend == I_(CLUTTER_INPUT_GDK)))
{
_clutter_backend_gdk_events_init (backend);
}
else
#endif
#ifdef CLUTTER_INPUT_EVDEV
/* Evdev can be used regardless of the windowing system */
if ((input_backend != NULL && strcmp (input_backend, CLUTTER_INPUT_EVDEV) == 0)

View File

@ -70,9 +70,6 @@
#include "clutter-stage-private.h"
#include "clutter-version.h" /* For flavour define */
#ifdef CLUTTER_WINDOWING_GDK
#include "gdk/clutter-backend-gdk.h"
#endif
#ifdef CLUTTER_WINDOWING_X11
#include "x11/clutter-backend-x11.h"
#endif
@ -3643,12 +3640,6 @@ clutter_check_windowing_backend (const char *backend_type)
return TRUE;
else
#endif
#ifdef CLUTTER_WINDOWING_GDK
if (backend_type == I_(CLUTTER_WINDOWING_GDK) &&
CLUTTER_IS_BACKEND_GDK (context->backend))
return TRUE;
else
#endif
#ifdef CLUTTER_WINDOWING_X11
if (backend_type == I_(CLUTTER_WINDOWING_X11) &&
CLUTTER_IS_BACKEND_X11 (context->backend))

View File

@ -38,10 +38,6 @@
#include "clutter-master-clock.h"
#include "clutter-master-clock-default.h"
#include "clutter-private.h"
#ifdef CLUTTER_WINDOWING_GDK
#include "gdk/clutter-backend-gdk.h"
#include "gdk/clutter-master-clock-gdk.h"
#endif
#define clutter_master_clock_get_type _clutter_master_clock_get_type
@ -60,14 +56,7 @@ _clutter_master_clock_get_default (void)
ClutterMainContext *context = _clutter_context_get_default ();
if (G_UNLIKELY (context->master_clock == NULL))
{
#ifdef CLUTTER_WINDOWING_GDK
if (CLUTTER_IS_BACKEND_GDK (context->backend))
context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_GDK, NULL);
else
#endif
context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, NULL);
}
context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, NULL);
return context->master_clock;

View File

@ -1,32 +0,0 @@
/* An OpenGL based 'interactive canvas' library.
* Authored By Matthew Allum <mallum@openedhand.com>
* Copyright (C) 2006-2007 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __CLUTTER_BACKEND_PRIVATE_X11_H__
#define __CLUTTER_BACKEND_PRIVATE_X11_H__
G_BEGIN_DECLS
void _clutter_backend_x11_events_init (ClutterBackend *backend);
void _clutter_backend_x11_events_uninit (ClutterBackend *backend);
G_END_DECLS
#endif

View File

@ -1,519 +0,0 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
* Authored By Matthew Allum <mallum@openedhand.com>
* Copyright (C) 2006-2007 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include <glib/gi18n-lib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <gdk/gdk.h>
#include <cogl/cogl.h>
#include <sys/ioctl.h>
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
#include <cogl/cogl-xlib.h>
#endif
#if defined(GDK_WINDOWING_WAYLAND) && defined(COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
#include <cogl/cogl-wayland-client.h>
#endif
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
#include "clutter-backend-gdk.h"
#include "clutter-device-manager-gdk.h"
#include "clutter-settings-gdk.h"
#include "clutter-stage-gdk.h"
#include "clutter-gdk.h"
#include "clutter-backend.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-event-private.h"
#include "clutter-main.h"
#include "clutter-private.h"
#include "clutter-settings-private.h"
G_DEFINE_TYPE (ClutterBackendGdk, clutter_backend_gdk, CLUTTER_TYPE_BACKEND);
/* global for pre init setup calls */
static GdkDisplay *_foreign_dpy = NULL;
static gboolean disable_event_retrieval = FALSE;
static void
clutter_backend_gdk_init_settings (ClutterBackendGdk *backend_gdk)
{
ClutterSettings *settings = clutter_settings_get_default ();
int i;
for (i = 0; i < G_N_ELEMENTS (_clutter_settings_map); i++)
{
GValue val = G_VALUE_INIT;
g_value_init (&val, CLUTTER_SETTING_TYPE(i));
if (gdk_screen_get_setting (backend_gdk->screen,
CLUTTER_SETTING_GDK_NAME (i),
&val))
{
clutter_settings_set_property_internal (settings,
CLUTTER_SETTING_PROPERTY (i),
&val);
}
g_value_unset (&val);
}
}
void
_clutter_backend_gdk_update_setting (ClutterBackendGdk *backend_gdk,
const gchar *setting_name)
{
ClutterSettings *settings = clutter_settings_get_default ();
int i;
for (i = 0; i < G_N_ELEMENTS (_clutter_settings_map); i++)
{
if (g_strcmp0 (CLUTTER_SETTING_GDK_NAME (i), setting_name) == 0)
{
GValue val = G_VALUE_INIT;
g_value_init (&val, CLUTTER_SETTING_TYPE (i));
gdk_screen_get_setting (backend_gdk->screen,
CLUTTER_SETTING_GDK_NAME (i),
&val);
clutter_settings_set_property_internal (settings,
CLUTTER_SETTING_PROPERTY (i),
&val);
g_value_unset (&val);
break;
}
}
}
static GdkFilterReturn
cogl_gdk_filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
#ifdef GDK_WINDOWING_X11
ClutterBackend *backend = data;
CoglFilterReturn ret;
ret = cogl_xlib_renderer_handle_event (backend->cogl_renderer, (XEvent *) xevent);
switch (ret)
{
case COGL_FILTER_REMOVE:
return GDK_FILTER_REMOVE;
case COGL_FILTER_CONTINUE:
default:
return GDK_FILTER_CONTINUE;
}
#endif
return GDK_FILTER_CONTINUE;
}
static gboolean
_clutter_backend_gdk_post_parse (ClutterBackend *backend,
GError **error)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
if (_foreign_dpy != NULL)
backend_gdk->display = _foreign_dpy;
/* Init Gdk, if outside code did not already */
if (!gdk_init_check (NULL, NULL))
{
g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND,
_("Could not initialize Gdk"));
return FALSE;
}
/*
* Only open connection if not already set by prior call to
* clutter_gdk_set_display()
*/
if (backend_gdk->display == NULL)
backend_gdk->display = g_object_ref (gdk_display_get_default ());
g_assert (backend_gdk->display != NULL);
backend_gdk->screen = gdk_display_get_default_screen (backend_gdk->display);
/* add event filter for Cogl events */
gdk_window_add_filter (NULL, cogl_gdk_filter, backend_gdk);
clutter_backend_gdk_init_settings (backend_gdk);
CLUTTER_NOTE (BACKEND,
"Gdk Display '%s' opened",
gdk_display_get_name (backend_gdk->display));
return TRUE;
}
static void
gdk_event_handler (GdkEvent *event,
gpointer user_data)
{
clutter_gdk_handle_event (event);
}
void
_clutter_backend_gdk_events_init (ClutterBackend *backend)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
CLUTTER_NOTE (EVENT, "initialising the event loop");
backend->device_manager =
g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_GDK,
"backend", backend,
"gdk-display", backend_gdk->display,
NULL);
if (!disable_event_retrieval)
gdk_event_handler_set (gdk_event_handler, NULL, NULL);
}
static void
clutter_backend_gdk_finalize (GObject *gobject)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (gobject);
gdk_window_remove_filter (NULL, cogl_gdk_filter, backend_gdk);
g_object_unref (backend_gdk->display);
G_OBJECT_CLASS (clutter_backend_gdk_parent_class)->finalize (gobject);
}
static void
clutter_backend_gdk_dispose (GObject *gobject)
{
G_OBJECT_CLASS (clutter_backend_gdk_parent_class)->dispose (gobject);
}
static ClutterFeatureFlags
clutter_backend_gdk_get_features (ClutterBackend *backend)
{
ClutterBackendClass *parent_class;
parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_gdk_parent_class);
return parent_class->get_features (backend)
| CLUTTER_FEATURE_STAGE_USER_RESIZE
| CLUTTER_FEATURE_STAGE_CURSOR;
}
static CoglRenderer *
clutter_backend_gdk_get_renderer (ClutterBackend *backend,
GError **error)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
CoglRenderer *renderer = cogl_renderer_new ();
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_DISPLAY (backend_gdk->display))
{
Display *xdisplay = gdk_x11_display_get_xdisplay (backend_gdk->display);
cogl_xlib_renderer_set_foreign_display (renderer, xdisplay);
}
else
#endif
#if defined(GDK_WINDOWING_WAYLAND) && defined(COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
if (GDK_IS_WAYLAND_DISPLAY (backend_gdk->display))
{
struct wl_display *display = gdk_wayland_display_get_wl_display (backend_gdk->display);
/* Force a Wayland winsys */
cogl_renderer_set_winsys_id (renderer, COGL_WINSYS_ID_EGL_WAYLAND);
cogl_wayland_renderer_set_foreign_display (renderer, display);
cogl_wayland_renderer_set_event_dispatch_enabled (renderer, !disable_event_retrieval);
}
else
#endif
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
_("Could not find a suitable CoglWinsys for a GdkDisplay of type %s"),
G_OBJECT_TYPE_NAME (backend_gdk->display));
cogl_object_unref (renderer);
return NULL;
}
return renderer;
}
static CoglDisplay *
clutter_backend_gdk_get_display (ClutterBackend *backend,
CoglRenderer *renderer,
CoglSwapChain *swap_chain,
GError **error)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
CoglOnscreenTemplate *onscreen_template;
GError *internal_error = NULL;
CoglDisplay *display;
gboolean has_rgba_visual;
gboolean res;
/* We default to an RGBA visual if there is one */
has_rgba_visual = gdk_screen_get_rgba_visual (backend_gdk->screen) != NULL;
CLUTTER_NOTE (BACKEND, "Alpha on Cogl swap chain: %s",
has_rgba_visual ? "enabled" : "disabled");
cogl_swap_chain_set_has_alpha (swap_chain, has_rgba_visual);
onscreen_template = cogl_onscreen_template_new (swap_chain);
res = cogl_renderer_check_onscreen_template (renderer,
onscreen_template,
&internal_error);
if (!res && has_rgba_visual)
{
CLUTTER_NOTE (BACKEND,
"Creation of a context with a ARGB visual failed: %s",
internal_error != NULL ? internal_error->message
: "Unknown reason");
g_clear_error (&internal_error);
/* It's possible that the current renderer doesn't support transparency
* in a swap_chain so lets see if we can fallback to not having any
* transparency...
*
* XXX: It might be nice to have a CoglRenderer feature we could
* explicitly check for ahead of time.
*/
cogl_swap_chain_set_has_alpha (swap_chain, FALSE);
res = cogl_renderer_check_onscreen_template (renderer,
onscreen_template,
&internal_error);
}
if (!res)
{
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
internal_error->message);
g_error_free (internal_error);
cogl_object_unref (onscreen_template);
return NULL;
}
display = cogl_display_new (renderer, onscreen_template);
cogl_object_unref (onscreen_template);
return display;
}
static void
clutter_backend_gdk_class_init (ClutterBackendGdkClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
gobject_class->dispose = clutter_backend_gdk_dispose;
gobject_class->finalize = clutter_backend_gdk_finalize;
backend_class->stage_window_type = CLUTTER_TYPE_STAGE_GDK;
backend_class->post_parse = _clutter_backend_gdk_post_parse;
backend_class->get_features = clutter_backend_gdk_get_features;
backend_class->get_renderer = clutter_backend_gdk_get_renderer;
backend_class->get_display = clutter_backend_gdk_get_display;
}
static void
clutter_backend_gdk_init (ClutterBackendGdk *backend_gdk)
{
/* Deactivate sync to vblank since we have the GdkFrameClock to
* drive us from the compositor.
*/
_clutter_set_sync_to_vblank (FALSE);
}
ClutterBackend *
clutter_backend_gdk_new (void)
{
return g_object_new (CLUTTER_TYPE_BACKEND_GDK, NULL);
}
/**
* clutter_gdk_get_default_display:
*
* Retrieves the pointer to the default display.
*
* Return value: (transfer none): the default display
*
* Since: 0.6
*/
GdkDisplay *
clutter_gdk_get_default_display (void)
{
ClutterBackend *backend = clutter_get_default_backend ();
if (backend == NULL)
{
g_critical ("The Clutter backend has not been initialised");
return NULL;
}
if (!CLUTTER_IS_BACKEND_GDK (backend))
{
g_critical ("The Clutter backend is not a GDK backend");
return NULL;
}
return CLUTTER_BACKEND_GDK (backend)->display;
}
/**
* clutter_gdk_set_display:
* @display: pointer to a GDK display connection.
*
* Sets the display connection Clutter should use; must be called
* before clutter_init(), clutter_init_with_args() or other functions
* pertaining Clutter's initialization process.
*
* If you are parsing the command line arguments by retrieving Clutter's
* #GOptionGroup with clutter_get_option_group() and calling
* g_option_context_parse() yourself, you should also call
* clutter_gdk_set_display() before g_option_context_parse().
*
* Since: 0.8
*/
void
clutter_gdk_set_display (GdkDisplay *display)
{
if (_clutter_context_is_initialized ())
{
g_warning ("%s() can only be used before calling clutter_init()",
G_STRFUNC);
return;
}
_foreign_dpy = g_object_ref (display);
}
/**
* clutter_gdk_disable_event_retrieval:
*
* Disable the event retrieval in Clutter.
*
* Callers of this function have to set up an event filter using the
* GDK API, and call clutter_gdk_handle_event().
*
* This function should only be used when embedding Clutter into
* a GDK based toolkit.
*
* Since: 1.10
*/
void
clutter_gdk_disable_event_retrieval (void)
{
if (_clutter_context_is_initialized ())
{
g_warning ("%s() can only be used before calling clutter_init()",
G_STRFUNC);
return;
}
disable_event_retrieval = TRUE;
}
/**
* clutter_gdk_get_visual:
*
* Retrieves the #GdkVisual used by Clutter.
*
* This function should be used when embedding Clutter inside GDK-based
* foreign toolkits, to ensure that the visual applied to the #GdkWindow
* used to render the #ClutterStage is the correct one.
*
* Returns: (transfer none): a #GdkVisual instance
*
* Since: 1.22
*/
GdkVisual *
clutter_gdk_get_visual (void)
{
ClutterBackend *backend = clutter_get_default_backend ();
GdkScreen *screen;
if (backend == NULL)
{
g_critical ("The Clutter backend has not been initialised");
return NULL;
}
if (!CLUTTER_IS_BACKEND_GDK (backend))
{
g_critical ("The Clutter backend is not a GDK backend");
return NULL;
}
screen = CLUTTER_BACKEND_GDK (backend)->screen;
g_assert (screen != NULL);
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_SCREEN (screen))
{
XVisualInfo *xvisinfo = cogl_xlib_renderer_get_visual_info (backend->cogl_renderer);
if (xvisinfo != NULL)
return gdk_x11_screen_lookup_visual (screen, xvisinfo->visualid);
}
#endif
if (gdk_screen_get_rgba_visual (screen) != NULL)
return gdk_screen_get_rgba_visual (screen);
return gdk_screen_get_system_visual (screen);
}

View File

@ -1,74 +0,0 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
* Authored By Matthew Allum <mallum@openedhand.com>
* Copyright (C) 2006-2007 OpenedHand
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __CLUTTER_BACKEND_GDK_H__
#define __CLUTTER_BACKEND_GDK_H__
#include <glib-object.h>
#include <clutter/clutter-event.h>
#include <gdk/gdk.h>
#include "clutter-gdk.h"
#include "clutter-backend-private.h"
G_BEGIN_DECLS
#define CLUTTER_TYPE_BACKEND_GDK (clutter_backend_gdk_get_type ())
#define CLUTTER_BACKEND_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_GDK, ClutterBackendGdk))
#define CLUTTER_IS_BACKEND_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_GDK))
#define CLUTTER_BACKEND_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_GDK, ClutterBackendGdkClass))
#define CLUTTER_IS_BACKEND_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_GDK))
#define CLUTTER_BACKEND_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_GDK, ClutterBackendGdkClass))
typedef struct _ClutterBackendGdk ClutterBackendGdk;
typedef struct _ClutterBackendGdkClass ClutterBackendGdkClass;
struct _ClutterBackendGdk
{
ClutterBackend parent_instance;
GdkDisplay *display;
GdkScreen *screen;
ClutterDeviceManager *device_manager;
};
struct _ClutterBackendGdkClass
{
ClutterBackendClass parent_class;
/* nothing here, for now */
};
GType clutter_backend_gdk_get_type (void) G_GNUC_CONST;
ClutterBackend *clutter_backend_gdk_new (void);
void _clutter_backend_gdk_events_init (ClutterBackend *backend);
void _clutter_backend_gdk_update_setting (ClutterBackendGdk *backend,
const gchar *name);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_GDK_H__ */

View File

@ -1,292 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corp.
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
#include "config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
/* XXX: We're using the GdkDeviceManager deprecated API because
* porting to the new GdkSeat API would imply adding an equivalent
* API to Clutter.
*/
#define GDK_DISABLE_DEPRECATION_WARNINGS
#include "clutter-device-manager-gdk.h"
#include "clutter-backend-gdk.h"
#include "clutter-input-device-gdk.h"
#include "clutter-stage-gdk.h"
#include "clutter-backend.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-event-private.h"
#include "clutter-event-translator.h"
#include "clutter-stage-private.h"
#include "clutter-private.h"
#define clutter_device_manager_gdk_get_type _clutter_device_manager_gdk_get_type
static void clutter_event_extender_iface_init (ClutterEventExtenderInterface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerGdk, clutter_device_manager_gdk,
CLUTTER_TYPE_DEVICE_MANAGER,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_EXTENDER,
clutter_event_extender_iface_init))
enum {
PROP_0,
PROP_GDK_DISPLAY,
PROP_LAST
};
static void
clutter_device_manager_gdk_copy_event_data (ClutterEventExtender *event_extender,
const ClutterEvent *src,
ClutterEvent *dest)
{
GdkEvent *gdk_event;
gdk_event = _clutter_event_get_platform_data (src);
if (gdk_event != NULL)
_clutter_event_set_platform_data (dest, gdk_event_copy (gdk_event));
}
static void
clutter_device_manager_gdk_free_event_data (ClutterEventExtender *event_extender,
ClutterEvent *event)
{
GdkEvent *gdk_event;
gdk_event = _clutter_event_get_platform_data (event);
if (gdk_event != NULL)
gdk_event_free (gdk_event);
}
static void
clutter_event_extender_iface_init (ClutterEventExtenderInterface *iface)
{
iface->copy_event_data = clutter_device_manager_gdk_copy_event_data;
iface->free_event_data = clutter_device_manager_gdk_free_event_data;
}
ClutterInputDevice *
_clutter_device_manager_gdk_lookup_device (ClutterDeviceManager *manager,
GdkDevice *device)
{
ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager);
ClutterInputDevice *clutter_device;
clutter_device = g_object_get_data (G_OBJECT (device), "clutter-device");
if (clutter_device != NULL)
return clutter_device;
clutter_device = _clutter_input_device_gdk_new (manager, device);
g_object_set_data_full (G_OBJECT (device), "clutter-device", clutter_device, g_object_unref);
manager_gdk->device_cache = g_slist_prepend (manager_gdk->device_cache, g_object_ref (clutter_device));
g_hash_table_replace (manager_gdk->device_by_id,
GINT_TO_POINTER (clutter_input_device_get_device_id (clutter_device)),
g_object_ref (clutter_device));
return clutter_device;
}
static void
clutter_device_manager_gdk_add_device (ClutterDeviceManager *manager,
ClutterInputDevice *device)
{
/* XXX implement */
}
static void
clutter_device_manager_gdk_remove_device (ClutterDeviceManager *manager,
ClutterInputDevice *device)
{
/* XXX implement */
}
static const GSList *
clutter_device_manager_gdk_get_devices (ClutterDeviceManager *manager)
{
ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager);
return manager_gdk->device_cache;
}
static ClutterInputDevice *
clutter_device_manager_gdk_get_device (ClutterDeviceManager *manager,
gint id)
{
ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager);
return g_hash_table_lookup (manager_gdk->device_by_id, GINT_TO_POINTER (id));
}
static ClutterInputDevice *
clutter_device_manager_gdk_get_core_device (ClutterDeviceManager *manager,
ClutterInputDeviceType device_type)
{
ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager);
GdkDevice *gdk_device;
gdk_device = gdk_device_manager_get_client_pointer (manager_gdk->device_manager);
g_assert (gdk_device != NULL);
if (device_type == CLUTTER_KEYBOARD_DEVICE)
gdk_device = gdk_device_get_associated_device (gdk_device);
else if (device_type != CLUTTER_POINTER_DEVICE)
return NULL;
return _clutter_device_manager_gdk_lookup_device (manager, gdk_device);
}
static void
gdk_device_added (GdkDeviceManager *gdk_manager,
GdkDevice *device,
ClutterDeviceManager *self)
{
/* this will do the right thing if the device is not there */
ClutterInputDevice *clutter_device = _clutter_device_manager_gdk_lookup_device (self, device);
_clutter_device_manager_add_device (self, clutter_device);
}
static void
gdk_device_removed (GdkDeviceManager *gdk_manager,
GdkDevice *device,
ClutterDeviceManagerGdk *self)
{
ClutterInputDevice *clutter_device = g_object_get_data (G_OBJECT (device), "clutter-device");
if (clutter_device == NULL)
return;
self->device_cache = g_slist_remove (self->device_cache, clutter_device);
g_object_unref (clutter_device);
g_hash_table_remove (self->device_by_id,
GINT_TO_POINTER (clutter_input_device_get_device_id (clutter_device)));
_clutter_device_manager_remove_device (CLUTTER_DEVICE_MANAGER (self), clutter_device);
}
static void
gdk_device_foreach_cb (gpointer data,
gpointer user_data)
{
_clutter_device_manager_gdk_lookup_device (user_data, data);
}
static void
clutter_device_manager_gdk_constructed (GObject *gobject)
{
ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (gobject);
GList *all_devices;
g_assert (manager_gdk->device_manager != NULL);
all_devices = gdk_device_manager_list_devices (manager_gdk->device_manager,
GDK_DEVICE_TYPE_MASTER);
g_list_foreach (all_devices, gdk_device_foreach_cb, manager_gdk);
g_list_free (all_devices);
all_devices = gdk_device_manager_list_devices (manager_gdk->device_manager,
GDK_DEVICE_TYPE_SLAVE);
g_list_foreach (all_devices, gdk_device_foreach_cb, manager_gdk);
g_list_free (all_devices);
all_devices = gdk_device_manager_list_devices (manager_gdk->device_manager,
GDK_DEVICE_TYPE_FLOATING);
g_list_foreach (all_devices, gdk_device_foreach_cb, manager_gdk);
g_list_free (all_devices);
g_object_connect (manager_gdk->device_manager,
"object-signal::device-added", gdk_device_added, gobject,
"object-signal::device-removed", gdk_device_removed, gobject,
NULL);
if (G_OBJECT_CLASS (clutter_device_manager_gdk_parent_class)->constructed)
G_OBJECT_CLASS (clutter_device_manager_gdk_parent_class)->constructed (gobject);
}
static void
clutter_device_manager_gdk_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (gobject);
GdkDisplay *gdk_display;
switch (prop_id)
{
case PROP_GDK_DISPLAY:
gdk_display = GDK_DISPLAY (g_value_get_object (value));
manager_gdk->device_manager = gdk_display_get_device_manager (gdk_display);
g_object_ref (manager_gdk->device_manager);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_device_manager_gdk_class_init (ClutterDeviceManagerGdkClass *klass)
{
ClutterDeviceManagerClass *manager_class;
GObjectClass *gobject_class;
GParamSpec *pspec;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = clutter_device_manager_gdk_constructed;
gobject_class->set_property = clutter_device_manager_gdk_set_property;
manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
manager_class->add_device = clutter_device_manager_gdk_add_device;
manager_class->remove_device = clutter_device_manager_gdk_remove_device;
manager_class->get_devices = clutter_device_manager_gdk_get_devices;
manager_class->get_core_device = clutter_device_manager_gdk_get_core_device;
manager_class->get_device = clutter_device_manager_gdk_get_device;
pspec = g_param_spec_object ("gdk-display",
"GdkDisplay",
"The GDK display",
GDK_TYPE_DISPLAY,
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (gobject_class, PROP_GDK_DISPLAY, pspec);
}
static void
clutter_device_manager_gdk_init (ClutterDeviceManagerGdk *self)
{
self->device_by_id = g_hash_table_new_full (NULL, NULL,
NULL, (GDestroyNotify) g_object_unref);
}

View File

@ -1,63 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DEVICE_MANAGER_GDK_H__
#define __CLUTTER_DEVICE_MANAGER_GDK_H__
#include <clutter/clutter-device-manager.h>
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DEVICE_MANAGER_GDK (_clutter_device_manager_gdk_get_type ())
#define CLUTTER_DEVICE_MANAGER_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_GDK, ClutterDeviceManagerGdk))
#define CLUTTER_IS_DEVICE_MANAGER_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_GDK))
#define CLUTTER_DEVICE_MANAGER_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_GDK, ClutterDeviceManagerGdkClass))
#define CLUTTER_IS_DEVICE_MANAGER_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_GDK))
#define CLUTTER_DEVICE_MANAGER_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_GDK, ClutterDeviceManagerGdkClass))
typedef struct _ClutterDeviceManagerGdk ClutterDeviceManagerGdk;
typedef struct _ClutterDeviceManagerGdkClass ClutterDeviceManagerGdkClass;
struct _ClutterDeviceManagerGdk
{
ClutterDeviceManager parent_instance;
GdkDeviceManager *device_manager;
GSList *device_cache;
GHashTable *device_by_id;
};
struct _ClutterDeviceManagerGdkClass
{
ClutterDeviceManagerClass parent_class;
};
GType _clutter_device_manager_gdk_get_type (void) G_GNUC_CONST;
ClutterInputDevice * _clutter_device_manager_gdk_lookup_device (ClutterDeviceManager *manager,
GdkDevice *device);
G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_GDK_H__ */

View File

@ -1,361 +0,0 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
* Copyright (C) 2009, 2010 Intel Corp.
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*
* Authored by:
* Matthew Allum <mallum@openedhand.com>
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#include "config.h"
#include "clutter-gdk.h"
#include "clutter-backend-gdk.h"
#include "clutter-device-manager-gdk.h"
#include "clutter-stage-gdk.h"
#include "clutter-actor-private.h"
#include "clutter-backend-private.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-event-private.h"
#include "clutter-main.h"
#include "clutter-paint-volume-private.h"
#include "clutter-stage-private.h"
#include <string.h>
#include <glib.h>
/**
* clutter_gdk_handle_event:
* @event: a #GdkEvent
*
* This function processes a single GDK event; it can be used to hook
* into external event processing
*
* Return value: #GdkFilterReturn. %GDK_FILTER_REMOVE indicates that
* Clutter has internally handled the event and the caller should do
* no further processing. %GDK_FILTER_CONTINUE indicates that Clutter
* is either not interested in the event, or has used the event to
* update internal state without taking any exclusive action.
* %GDK_FILTER_TRANSLATE will not occur.
*
*/
GdkFilterReturn
clutter_gdk_handle_event (GdkEvent *gdk_event)
{
ClutterDeviceManager *device_manager;
ClutterBackendGdk *backend_gdk;
ClutterBackend *backend;
ClutterStage *stage = NULL;
ClutterEvent *event = NULL;
gint spin = 0;
GdkFilterReturn result = GDK_FILTER_CONTINUE;
ClutterInputDevice *device, *source_device;
GdkDevice *gdk_device;
backend = clutter_get_default_backend ();
if (!CLUTTER_IS_BACKEND_GDK (backend))
return GDK_FILTER_CONTINUE;
if (gdk_event->any.window == NULL)
return GDK_FILTER_CONTINUE;
device_manager = clutter_device_manager_get_default ();
if (G_UNLIKELY (device_manager == NULL))
return GDK_FILTER_CONTINUE;
backend_gdk = CLUTTER_BACKEND_GDK (backend);
stage = clutter_gdk_get_stage_from_window (gdk_event->any.window);
gdk_device = gdk_event_get_device (gdk_event);
if (gdk_device != NULL)
device = _clutter_device_manager_gdk_lookup_device (device_manager,
gdk_device);
else
device = NULL;
gdk_device = gdk_event_get_source_device (gdk_event);
if (gdk_device != NULL)
source_device = _clutter_device_manager_gdk_lookup_device (device_manager,
gdk_device);
else
source_device = NULL;
if (stage == NULL)
return GDK_FILTER_CONTINUE;
_clutter_threads_acquire_lock ();
switch (gdk_event->type)
{
case GDK_DELETE:
event = clutter_event_new (CLUTTER_DELETE);
break;
case GDK_DESTROY:
event = clutter_event_new (CLUTTER_DESTROY_NOTIFY);
break;
case GDK_EXPOSE:
{
ClutterPaintVolume clip;
ClutterVertex origin;
CLUTTER_NOTE (EVENT, "Expose for stage '%s' [%p] { %d, %d - %d x %d }",
_clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
stage,
gdk_event->expose.area.x,
gdk_event->expose.area.y,
gdk_event->expose.area.width,
gdk_event->expose.area.height);
origin.x = gdk_event->expose.area.x;
origin.y = gdk_event->expose.area.y;
origin.z = 0;
_clutter_paint_volume_init_static (&clip, CLUTTER_ACTOR (stage));
clutter_paint_volume_set_origin (&clip, &origin);
clutter_paint_volume_set_width (&clip, gdk_event->expose.area.width);
clutter_paint_volume_set_height (&clip, gdk_event->expose.area.height);
_clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip);
clutter_paint_volume_free (&clip);
}
break;
case GDK_DAMAGE:
/* This is handled by cogl */
break;
case GDK_MOTION_NOTIFY:
event = clutter_event_new (CLUTTER_MOTION);
event->motion.time = gdk_event->motion.time;
event->motion.x = gdk_event->motion.x;
event->motion.y = gdk_event->motion.y;
event->motion.axes = NULL;
/* It's all X in the end, right? */
event->motion.modifier_state = gdk_event->motion.state;
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
CLUTTER_NOTE (EVENT, "Motion notifiy [%.2f, %.2f]",
event->motion.x,
event->motion.y);
break;
case GDK_BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
event = clutter_event_new (gdk_event->type == GDK_BUTTON_PRESS ?
CLUTTER_BUTTON_PRESS :
CLUTTER_BUTTON_RELEASE);
event->button.time = gdk_event->button.time;
event->button.x = gdk_event->button.x;
event->button.y = gdk_event->button.y;
event->button.axes = NULL;
event->button.modifier_state = gdk_event->button.state;
event->button.button = gdk_event->button.button;
event->button.click_count = 1;
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
CLUTTER_NOTE (EVENT, "Button %d %s [%.2f, %.2f]",
event->button.button,
event->type == CLUTTER_BUTTON_PRESS ? "press" : "release",
event->button.x,
event->button.y);
break;
case GDK_TOUCH_BEGIN:
case GDK_TOUCH_END:
case GDK_TOUCH_CANCEL:
case GDK_TOUCH_UPDATE:
event = clutter_event_new (gdk_event->type == GDK_TOUCH_BEGIN ?
CLUTTER_TOUCH_BEGIN :
((gdk_event->type == GDK_TOUCH_END) ?
CLUTTER_TOUCH_END :
(gdk_event->type == GDK_TOUCH_UPDATE ?
CLUTTER_TOUCH_UPDATE :
CLUTTER_TOUCH_CANCEL)));
event->touch.time = gdk_event->touch.time;
event->touch.x = gdk_event->touch.x;
event->touch.y = gdk_event->touch.y;
event->touch.sequence = (ClutterEventSequence *) gdk_event->touch.sequence;
event->touch.modifier_state = gdk_event->touch.state;
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
CLUTTER_NOTE (EVENT, "Touch %p %s [%",
event->touch.sequence,
event->type == CLUTTER_TOUCH_BEGIN ? "begin" :
(event->type == CLUTTER_TOUCH_END ? "end" :
(event->type == CLUTTER_TOUCH_UPDATE ? "update"
: "cancel")),
event->touch.x, event->touch.y);
break;
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
/* these are handled by clutter-main.c updating click_count */
break;
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
event = clutter_event_new (gdk_event->type == GDK_KEY_PRESS ?
CLUTTER_KEY_PRESS :
CLUTTER_KEY_RELEASE);
event->key.time = gdk_event->key.time;
event->key.modifier_state = gdk_event->key.state;
event->key.keyval = gdk_event->key.keyval;
event->key.hardware_keycode = gdk_event->key.hardware_keycode;
event->key.unicode_value = g_utf8_get_char (gdk_event->key.string);
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
CLUTTER_NOTE (EVENT, "Key %d %s",
event->key.keyval,
event->type == CLUTTER_KEY_PRESS ? "press" : "release");
break;
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
event = clutter_event_new (gdk_event->type == GDK_ENTER_NOTIFY ?
CLUTTER_ENTER :
CLUTTER_LEAVE);
event->crossing.source = CLUTTER_ACTOR (stage);
event->crossing.time = gdk_event_get_time (gdk_event);
event->crossing.x = gdk_event->crossing.x;
event->crossing.y = gdk_event->crossing.y;
/* XXX: no better fallback here? */
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
if (gdk_event->type == GDK_ENTER_NOTIFY)
_clutter_input_device_set_stage (clutter_event_get_device (event), stage);
else if (gdk_event->type == GDK_LEAVE_NOTIFY &&
gdk_event->crossing.mode != GDK_CROSSING_TOUCH_BEGIN &&
gdk_event->crossing.mode != GDK_CROSSING_TOUCH_END &&
gdk_event->crossing.mode != GDK_CROSSING_DEVICE_SWITCH)
_clutter_input_device_set_stage (clutter_event_get_device (event), NULL);
CLUTTER_NOTE (EVENT, "Crossing %s [%.2f, %.2f]",
event->type == CLUTTER_ENTER ? "enter" : "leave",
event->crossing.x,
event->crossing.y);
break;
case GDK_FOCUS_CHANGE:
if (gdk_event->focus_change.in)
_clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED);
else
_clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0);
break;
case GDK_CONFIGURE:
{
gfloat w, h;
clutter_actor_get_size (CLUTTER_ACTOR (stage), &w, &h);
/* Notify gdk stage backend of the new position. This is used
by foreign stages to reposition themselves on wayland. */
_clutter_stage_gdk_notify_configure (CLUTTER_STAGE_GDK (_clutter_stage_get_window (stage)),
gdk_event->configure.x,
gdk_event->configure.y,
gdk_event->configure.width,
gdk_event->configure.height);
if ((int) w != gdk_event->configure.width ||
(int) h != gdk_event->configure.height)
{
clutter_actor_set_size (CLUTTER_ACTOR (stage),
gdk_event->configure.width,
gdk_event->configure.height);
}
}
break;
case GDK_SCROLL:
event = clutter_event_new (CLUTTER_SCROLL);
event->scroll.time = gdk_event->scroll.time;
event->scroll.x = gdk_event->scroll.x;
event->scroll.y = gdk_event->scroll.y;
event->scroll.modifier_state = gdk_event->scroll.state;
event->scroll.axes = NULL;
/* XXX: must keep ClutterScrollDirection compatible with GdkScrollDirection */
event->scroll.direction = (ClutterScrollDirection) gdk_event->scroll.direction;
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
clutter_event_set_scroll_delta (event,
gdk_event->scroll.delta_x,
gdk_event->scroll.delta_y);
break;
case GDK_WINDOW_STATE:
if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
{
gboolean is_fullscreen;
is_fullscreen = (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
if (is_fullscreen)
_clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_FULLSCREEN);
else
_clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_FULLSCREEN, 0);
}
break;
case GDK_SETTING:
_clutter_backend_gdk_update_setting (backend_gdk, gdk_event->setting.name);
break;
default:
break;
}
if (event != NULL)
{
event->any.stage = stage;
if (gdk_event->any.send_event)
event->any.flags = CLUTTER_EVENT_FLAG_SYNTHETIC;
_clutter_event_push (event, FALSE);
spin = 1;
CLUTTER_NOTE (EVENT, "Translated one event from Gdk");
/* handle also synthetic enter/leave events */
if (event->type == CLUTTER_MOTION)
spin += 2;
while (spin > 0 && (event = clutter_event_get ()))
{
/* forward the event into clutter for emission etc. */
_clutter_stage_queue_event (event->any.stage, event, FALSE);
--spin;
}
result = GDK_FILTER_REMOVE;
}
_clutter_threads_release_lock ();
return result;
}

View File

@ -1,69 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
/**
* SECTION:clutter-gdk
* @short_description: GDK specific API
*
* The GDK backend for Clutter provides some specific API, allowing
* integration with the GDK API for manipulating the stage window and
* handling events outside of Clutter.
*/
#ifndef __CLUTTER_GDK_H__
#define __CLUTTER_GDK_H__
#include <glib.h>
#include <gdk/gdk.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
CLUTTER_AVAILABLE_IN_1_10
GdkDisplay * clutter_gdk_get_default_display (void);
CLUTTER_AVAILABLE_IN_1_10
void clutter_gdk_set_display (GdkDisplay *display);
CLUTTER_AVAILABLE_IN_1_10
GdkWindow * clutter_gdk_get_stage_window (ClutterStage *stage);
CLUTTER_AVAILABLE_IN_1_10
gboolean clutter_gdk_set_stage_foreign (ClutterStage *stage,
GdkWindow *window);
CLUTTER_AVAILABLE_IN_1_10
GdkFilterReturn clutter_gdk_handle_event (GdkEvent *event);
CLUTTER_AVAILABLE_IN_1_10
ClutterStage * clutter_gdk_get_stage_from_window (GdkWindow *window);
CLUTTER_AVAILABLE_IN_1_10
void clutter_gdk_disable_event_retrieval (void);
CLUTTER_AVAILABLE_IN_1_22
GdkVisual * clutter_gdk_get_visual (void);
G_END_DECLS
#endif /* __CLUTTER_GDK_H__ */

View File

@ -1,189 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corp.
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
#include "config.h"
#include "clutter-input-device-gdk.h"
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-backend-gdk.h"
#include "clutter-stage-gdk.h"
typedef struct _ClutterInputDeviceClass ClutterInputDeviceGdkClass;
#define clutter_input_device_gdk_get_type _clutter_input_device_gdk_get_type
G_DEFINE_TYPE (ClutterInputDeviceGdk,
clutter_input_device_gdk,
CLUTTER_TYPE_INPUT_DEVICE);
static int device_int_counter;
enum {
PROP_0,
PROP_GDK_DEVICE,
PROP_LAST
};
static void
clutter_input_device_gdk_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterInputDeviceGdk *self = CLUTTER_INPUT_DEVICE_GDK (gobject);
switch (prop_id)
{
case PROP_GDK_DEVICE:
self->gdk_device = GDK_DEVICE (g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_input_device_gdk_class_init (ClutterInputDeviceGdkClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = clutter_input_device_gdk_set_property;
g_object_class_install_property (gobject_class, PROP_GDK_DEVICE,
g_param_spec_object ("gdk-device",
"GdkDevice",
"The GDK device",
GDK_TYPE_DEVICE,
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}
static void
clutter_input_device_gdk_init (ClutterInputDeviceGdk *self)
{
}
ClutterInputDevice*
_clutter_input_device_gdk_new (ClutterDeviceManager *manager,
GdkDevice *device)
{
ClutterBackend *backend;
ClutterInputDevice *clutter_device;
ClutterInputMode input_mode = CLUTTER_INPUT_MODE_FLOATING;
ClutterInputDeviceType device_type = CLUTTER_EXTENSION_DEVICE;
gboolean has_cursor = FALSE;
const gchar *name;
gboolean is_enabled = FALSE;
gint device_id;
const char *vendor_id = NULL;
const char *product_id = NULL;
g_object_get (manager, "backend", &backend, NULL);
/* yay for name consistency */
switch (gdk_device_get_device_type (device))
{
case GDK_DEVICE_TYPE_MASTER:
input_mode = CLUTTER_INPUT_MODE_MASTER;
is_enabled = TRUE;
break;
case GDK_DEVICE_TYPE_SLAVE:
input_mode = CLUTTER_INPUT_MODE_SLAVE;
is_enabled = FALSE;
break;
case GDK_DEVICE_TYPE_FLOATING:
input_mode = CLUTTER_INPUT_MODE_FLOATING;
is_enabled = FALSE;
break;
}
switch (gdk_device_get_source (device))
{
case GDK_SOURCE_MOUSE:
device_type = CLUTTER_POINTER_DEVICE;
break;
case GDK_SOURCE_PEN:
device_type = CLUTTER_PEN_DEVICE;
break;
case GDK_SOURCE_ERASER:
device_type = CLUTTER_ERASER_DEVICE;
break;
case GDK_SOURCE_CURSOR:
device_type = CLUTTER_CURSOR_DEVICE;
break;
case GDK_SOURCE_KEYBOARD:
device_type = CLUTTER_KEYBOARD_DEVICE;
break;
case GDK_SOURCE_TOUCHSCREEN:
device_type = CLUTTER_TOUCHSCREEN_DEVICE;
break;
case GDK_SOURCE_TOUCHPAD:
device_type = CLUTTER_TOUCHPAD_DEVICE;
break;
}
if (device_type != CLUTTER_KEYBOARD_DEVICE)
has_cursor = gdk_device_get_has_cursor (device);
name = gdk_device_get_name (device);
#if defined(GDK_WINDOWING_X11)
/* If we're on X11, keep the device id in sync */
if (GDK_IS_X11_DISPLAY (gdk_device_get_display (device)))
device_id = gdk_x11_device_get_id (device);
else
#endif
device_id = device_int_counter++;
if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
{
product_id = gdk_device_get_product_id (device);
vendor_id = gdk_device_get_vendor_id (device);
}
clutter_device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_GDK,
"backend", backend,
"device-manager", manager,
"device-mode", input_mode,
"device-type", device_type,
"has-cursor", has_cursor,
"gdk-device", device,
"id", device_id,
"name", name,
"enabled", is_enabled,
"product-id", product_id,
"vendor-id", vendor_id,
NULL);
return clutter_device;
}

View File

@ -1,55 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_INPUT_DEVICE_GDK_H__
#define __CLUTTER_INPUT_DEVICE_GDK_H__
#include <clutter/clutter-input-device.h>
#include <gdk/gdk.h>
#include "clutter-backend.h"
#include "clutter-device-manager-private.h"
G_BEGIN_DECLS
#define CLUTTER_TYPE_INPUT_DEVICE_GDK (_clutter_input_device_gdk_get_type ())
#define CLUTTER_INPUT_DEVICE_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_GDK, ClutterInputDeviceGdk))
#define CLUTTER_IS_INPUT_DEVICE_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_GDK))
typedef struct _ClutterInputDeviceGdk ClutterInputDeviceGdk;
struct _ClutterInputDeviceGdk
{
ClutterInputDevice parent;
GdkDevice *gdk_device;
};
GType _clutter_input_device_gdk_get_type (void) G_GNUC_CONST;
ClutterInputDevice * _clutter_input_device_gdk_new (ClutterDeviceManager *manager,
GdkDevice *device);
G_END_DECLS
#endif /* __CLUTTER_INPUT_DEVICE_GDK_H__ */

View File

@ -1,594 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com>
*
* Copyright (C) 2015 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* SECTION:clutter-master-clock-gdk
* @short_description: The GDK master clock for all animations
*
* The #ClutterMasterClockDefault class is the GdkFrameClock based implementation
* of #ClutterMasterClock.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gdk/gdk.h>
#include "clutter-master-clock.h"
#include "clutter-master-clock-gdk.h"
#include "clutter-stage-gdk.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
#ifdef CLUTTER_ENABLE_DEBUG
#define clutter_warn_if_over_budget(master_clock,start_time,section) G_STMT_START { \
gint64 __delta = g_get_monotonic_time () - start_time; \
gint64 __budget = master_clock->remaining_budget; \
if (__budget > 0 && __delta >= __budget) { \
_clutter_diagnostic_message ("%s took %" G_GINT64_FORMAT " microseconds " \
"more than the remaining budget of %" G_GINT64_FORMAT \
" microseconds", \
section, __delta - __budget, __budget); \
} } G_STMT_END
#else
#define clutter_warn_if_over_budget(master_clock,start_time,section)
#endif
typedef struct _ClutterClockSource ClutterClockSource;
struct _ClutterMasterClockGdk
{
GObject parent_instance;
/* the list of timelines handled by the clock */
GSList *timelines;
/* mapping between ClutterStages and GdkFrameClocks.
*
* @stage_to_clock: a direct mapping because each stage has at most one clock
* @clock_to_stage: each clock can have more than one stage
*/
GHashTable *stage_to_clock;
GHashTable *clock_to_stage;
/* the current state of the clock, in usecs */
gint64 cur_tick;
/* the previous state of the clock, in usecs, used to compute the delta */
gint64 prev_tick;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 frame_budget;
gint64 remaining_budget;
#endif
};
struct _ClutterClockSource
{
GSource source;
ClutterMasterClock *master_clock;
};
static void clutter_master_clock_iface_init (ClutterMasterClockIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterMasterClockGdk,
clutter_master_clock_gdk,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_MASTER_CLOCK,
clutter_master_clock_iface_init));
static void
master_clock_schedule_forced_stages_updates (ClutterMasterClockGdk *master_clock)
{
GHashTableIter iter;
gpointer stage, frame_clock;
g_hash_table_iter_init (&iter, master_clock->stage_to_clock);
while (g_hash_table_iter_next (&iter, &stage, &frame_clock))
gdk_frame_clock_request_phase (GDK_FRAME_CLOCK (frame_clock),
GDK_FRAME_CLOCK_PHASE_PAINT);
}
static void
master_clock_sync_frame_clock_update (ClutterMasterClockGdk *master_clock)
{
gboolean updating = master_clock->timelines != NULL;
gpointer frame_clock, stage_list;
GHashTableIter iter;
g_hash_table_iter_init (&iter, master_clock->clock_to_stage);
while (g_hash_table_iter_next (&iter, &frame_clock, &stage_list))
{
gboolean clock_updating =
GPOINTER_TO_UINT (g_object_get_data (frame_clock,
"clutter-master-clock-updating"));
if (clock_updating != updating)
{
if (updating)
gdk_frame_clock_begin_updating (GDK_FRAME_CLOCK (frame_clock));
else
gdk_frame_clock_end_updating (GDK_FRAME_CLOCK (frame_clock));
g_object_set_data (frame_clock,
"clutter-master-clock-updating",
GUINT_TO_POINTER (updating));
}
}
}
static void
master_clock_schedule_stage_update (ClutterMasterClockGdk *master_clock,
ClutterStage *stage,
GdkFrameClock *frame_clock)
{
/* Clear the old update time */
_clutter_stage_clear_update_time (stage);
/* And if there is still work to be done, schedule a new one */
if (_clutter_stage_has_queued_events (stage) ||
_clutter_stage_needs_update (stage))
_clutter_stage_schedule_update (stage);
/* We can avoid to schedule a new frame if the stage doesn't need
* anymore redrawing. But in the case we still have timelines alive,
* we have no choice, we need to advance the timelines for the next
* frame. */
if (master_clock->timelines != NULL)
gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_PAINT);
}
static void
master_clock_process_stage_events (ClutterMasterClockGdk *master_clock,
ClutterStage *stage)
{
#ifdef CLUTTER_ENABLE_DEBUG
gint64 start = g_get_monotonic_time ();
#endif
/* Process queued events */
_clutter_stage_process_queued_events (stage);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Event processing");
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
#endif
}
/*
* master_clock_advance_timelines:
* @master_clock: a #ClutterMasterClock
*
* Advances all the timelines held by the master clock. This function
* should be called before calling _clutter_stage_do_update() to
* make sure that all the timelines are advanced and the scene is updated.
*/
static void
master_clock_advance_timelines (ClutterMasterClockGdk *master_clock)
{
GSList *timelines, *l;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 start = g_get_monotonic_time ();
#endif
/* we protect ourselves from timelines being removed during
* the advancement by other timelines by copying the list of
* timelines, taking a reference on them, iterating over the
* copied list and then releasing the reference.
*
* we cannot simply take a reference on the timelines and still
* use the list held by the master clock because the do_tick()
* might result in the creation of a new timeline, which gets
* added at the end of the list with no reference increase and
* thus gets disposed at the end of the iteration.
*
* this implies that a newly added timeline will not be advanced
* by this clock iteration, which is perfectly fine since we're
* in its first cycle.
*
* we also cannot steal the master clock timelines list because
* a timeline might be removed as the direct result of do_tick()
* and remove_timeline() would not find the timeline, failing
* and leaving a dangling pointer behind.
*/
timelines = g_slist_copy (master_clock->timelines);
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
for (l = timelines; l != NULL; l = l->next)
_clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000);
g_slist_foreach (timelines, (GFunc) g_object_unref, NULL);
g_slist_free (timelines);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Animations");
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
#endif
}
static gboolean
master_clock_update_stage (ClutterMasterClockGdk *master_clock,
ClutterStage *stage)
{
gboolean stage_updated = FALSE;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 start = g_get_monotonic_time ();
#endif
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT);
/* Update any stage that needs redraw/relayout after the clock
* is advanced.
*/
stage_updated |= _clutter_stage_do_update (stage);
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Updating the stage");
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
#endif
return stage_updated;
}
static void
clutter_master_clock_gdk_update (GdkFrameClock *frame_clock,
ClutterMasterClockGdk *master_clock)
{
GList *stages, *l;
_clutter_threads_acquire_lock ();
/* Get the time to use for this frame */
master_clock->cur_tick = gdk_frame_clock_get_frame_time (frame_clock);
#ifdef CLUTTER_ENABLE_DEBUG
/* Update the remaining budget */
master_clock->remaining_budget = master_clock->frame_budget;
#endif
stages = g_hash_table_lookup (master_clock->clock_to_stage, frame_clock);
CLUTTER_NOTE (SCHEDULER, "Updating %d stages tied to frame clock %p",
g_list_length (stages), frame_clock);
for (l = stages; l != NULL; l = l->next)
{
ClutterStage *stage = l->data;
CLUTTER_NOTE (SCHEDULER, "Master clock (stage:%p, clock:%p) [tick]", stage, frame_clock);
/* Each frame is split into three separate phases: */
/* 1. process all the events; goes through the stage's event queue
* and processes each event according to its type, then emits the
* various signals that are associated with the event
*/
master_clock_process_stage_events (master_clock, stage);
/* 2. advance the timelines */
master_clock_advance_timelines (master_clock);
/* 3. relayout and redraw the stage; the stage might have been
* destroyed in 1. when processing events, check whether it's
* still alive.
*/
if (g_hash_table_lookup (master_clock->stage_to_clock, stage) != NULL)
{
master_clock_update_stage (master_clock, stage);
master_clock_schedule_stage_update (master_clock, stage, frame_clock);
}
}
master_clock->prev_tick = master_clock->cur_tick;
_clutter_threads_release_lock ();
}
static void
clutter_master_clock_gdk_remove_stage_clock (ClutterMasterClockGdk *master_clock,
ClutterStage *stage)
{
gpointer frame_clock = g_hash_table_lookup (master_clock->stage_to_clock, stage);
GList *stages;
if (frame_clock == NULL)
return;
CLUTTER_NOTE (SCHEDULER, "Removing stage %p with clock %p", stage, frame_clock);
g_hash_table_remove (master_clock->stage_to_clock, stage);
stages = g_hash_table_lookup (master_clock->clock_to_stage, frame_clock);
if (stages != NULL)
{
if (stages->next == NULL)
{
/* Deleting the last stage linked to a given clock. We can stop
listening to that clock and also tell the clock we're finish
updating it. */
if (GPOINTER_TO_UINT (g_object_get_data (frame_clock,
"clutter-master-clock-updating")))
{
gdk_frame_clock_end_updating (GDK_FRAME_CLOCK (frame_clock));
g_object_set_data (frame_clock, "clutter-master-clock-updating", NULL);
}
g_signal_handlers_disconnect_by_func (frame_clock,
clutter_master_clock_gdk_update,
master_clock);
g_hash_table_remove (master_clock->clock_to_stage, frame_clock);
g_list_free (stages);
}
else
{
stages = g_list_remove (stages, stage);
g_hash_table_replace (master_clock->clock_to_stage,
g_object_ref (frame_clock),
stages);
}
}
}
static void
clutter_master_clock_gdk_add_stage_clock (ClutterMasterClockGdk *master_clock,
ClutterStage *stage,
GdkFrameClock *frame_clock)
{
GList *stages;
clutter_master_clock_gdk_remove_stage_clock (master_clock, stage);
CLUTTER_NOTE (SCHEDULER, "Adding stage %p with clock %p", stage, frame_clock);
g_hash_table_insert (master_clock->stage_to_clock, stage, g_object_ref (frame_clock));
stages = g_hash_table_lookup (master_clock->clock_to_stage, frame_clock);
if (stages == NULL)
{
g_hash_table_insert (master_clock->clock_to_stage, g_object_ref (frame_clock),
g_list_append (NULL, stage));
g_signal_connect (frame_clock, "paint",
G_CALLBACK (clutter_master_clock_gdk_update),
master_clock);
}
else
stages = g_list_append (stages, stage);
if (master_clock->timelines != NULL)
{
_clutter_master_clock_start_running ((ClutterMasterClock *) master_clock);
/* We only need to synchronize the frame clock state if we have
timelines running. */
master_clock_sync_frame_clock_update (master_clock);
}
}
static void
clutter_master_clock_gdk_listen_to_stage (ClutterMasterClockGdk *master_clock,
ClutterStage *stage)
{
ClutterStageWindow *stage_window;
ClutterStageGdk *stage_window_gdk;
GdkFrameClock *frame_clock;
stage_window = _clutter_stage_get_window (stage);
if (stage_window == NULL)
{
clutter_master_clock_gdk_remove_stage_clock (master_clock, stage);
return;
}
stage_window_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_window_gdk->window == NULL)
{
clutter_master_clock_gdk_remove_stage_clock (master_clock, stage);
return;
}
frame_clock = gdk_window_get_frame_clock (stage_window_gdk->window);
if (frame_clock == NULL)
{
clutter_master_clock_gdk_remove_stage_clock (master_clock, stage);
return;
}
clutter_master_clock_gdk_add_stage_clock (master_clock, stage, frame_clock);
}
static void
clutter_master_clock_gdk_stage_visibility (ClutterStage *stage,
GParamSpec *spec,
ClutterMasterClockGdk *master_clock)
{
ClutterActor *actor = CLUTTER_ACTOR (stage);
if (clutter_actor_is_mapped (actor))
clutter_master_clock_gdk_listen_to_stage (master_clock, stage);
else
clutter_master_clock_gdk_remove_stage_clock (master_clock, stage);
}
static void
clutter_master_clock_gdk_stage_added (ClutterStageManager *manager,
ClutterStage *stage,
ClutterMasterClockGdk *master_clock)
{
g_signal_connect (stage, "notify::mapped",
G_CALLBACK (clutter_master_clock_gdk_stage_visibility),
master_clock);
clutter_master_clock_gdk_stage_visibility (stage, NULL, master_clock);
}
static void
clutter_master_clock_gdk_stage_removed (ClutterStageManager *manager,
ClutterStage *stage,
ClutterMasterClockGdk *master_clock)
{
clutter_master_clock_gdk_remove_stage_clock (master_clock, stage);
g_signal_handlers_disconnect_by_func (stage,
clutter_master_clock_gdk_stage_visibility,
master_clock);
}
static void
clutter_master_clock_gdk_dispose (GObject *gobject)
{
ClutterStageManager *manager = clutter_stage_manager_get_default ();
g_signal_handlers_disconnect_by_func (manager,
clutter_master_clock_gdk_stage_added,
gobject);
g_signal_handlers_disconnect_by_func (manager,
clutter_master_clock_gdk_stage_removed,
gobject);
G_OBJECT_CLASS (clutter_master_clock_gdk_parent_class)->dispose (gobject);
}
static void
clutter_master_clock_gdk_finalize (GObject *gobject)
{
ClutterMasterClockGdk *master_clock = CLUTTER_MASTER_CLOCK_GDK (gobject);
g_hash_table_unref (master_clock->clock_to_stage);
g_hash_table_unref (master_clock->stage_to_clock);
g_slist_free (master_clock->timelines);
G_OBJECT_CLASS (clutter_master_clock_gdk_parent_class)->finalize (gobject);
}
static void
clutter_master_clock_gdk_class_init (ClutterMasterClockGdkClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = clutter_master_clock_gdk_dispose;
gobject_class->finalize = clutter_master_clock_gdk_finalize;
}
static void
clutter_master_clock_gdk_init (ClutterMasterClockGdk *self)
{
ClutterStageManager *manager;
const GSList *stages, *l;
#ifdef CLUTTER_ENABLE_DEBUG
self->frame_budget = G_USEC_PER_SEC / 60;
#endif
self->clock_to_stage = g_hash_table_new_full (g_direct_hash, g_direct_equal,
g_object_unref, NULL);
self->stage_to_clock = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_object_unref);
manager = clutter_stage_manager_get_default ();
g_signal_connect (manager, "stage-added",
G_CALLBACK (clutter_master_clock_gdk_stage_added), self);
g_signal_connect (manager, "stage-removed",
G_CALLBACK (clutter_master_clock_gdk_stage_removed), self);
stages = clutter_stage_manager_peek_stages (manager);
for (l = stages; l; l = l->next)
clutter_master_clock_gdk_stage_added (manager, l->data, self);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_CONTINUOUS_REDRAW))
g_warning ("Continuous redraw is not supported with the GDK backend.");
}
static void
clutter_master_clock_gdk_add_timeline (ClutterMasterClock *clock,
ClutterTimeline *timeline)
{
ClutterMasterClockGdk *master_clock = (ClutterMasterClockGdk *) clock;
gboolean is_first;
if (g_slist_find (master_clock->timelines, timeline))
return;
is_first = master_clock->timelines == NULL;
master_clock->timelines = g_slist_prepend (master_clock->timelines,
timeline);
if (is_first)
{
_clutter_master_clock_start_running (clock);
/* Sync frame clock update state if needed. */
master_clock_sync_frame_clock_update (master_clock);
}
}
static void
clutter_master_clock_gdk_remove_timeline (ClutterMasterClock *clock,
ClutterTimeline *timeline)
{
ClutterMasterClockGdk *master_clock = (ClutterMasterClockGdk *) clock;
master_clock->timelines = g_slist_remove (master_clock->timelines,
timeline);
/* Sync frame clock update state if we have no more timelines running. */
if (master_clock->timelines == NULL)
master_clock_sync_frame_clock_update (master_clock);
}
static void
clutter_master_clock_gdk_start_running (ClutterMasterClock *clock)
{
master_clock_schedule_forced_stages_updates ((ClutterMasterClockGdk *) clock);
}
static void
clutter_master_clock_gdk_ensure_next_iteration (ClutterMasterClock *clock)
{
master_clock_schedule_forced_stages_updates ((ClutterMasterClockGdk *) clock);
}
static void
clutter_master_clock_gdk_set_paused (ClutterMasterClock *clock,
gboolean paused)
{
/* GdkFrameClock runs the show here. We do not decide whether the
clock is paused or not. */
}
static void
clutter_master_clock_iface_init (ClutterMasterClockIface *iface)
{
iface->add_timeline = clutter_master_clock_gdk_add_timeline;
iface->remove_timeline = clutter_master_clock_gdk_remove_timeline;
iface->start_running = clutter_master_clock_gdk_start_running;
iface->ensure_next_iteration = clutter_master_clock_gdk_ensure_next_iteration;
iface->set_paused = clutter_master_clock_gdk_set_paused;
}

View File

@ -1,48 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com>
*
* Copyright (C) 2015 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CLUTTER_MASTER_CLOCK_GDK_H__
#define __CLUTTER_MASTER_CLOCK_GDK_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_MASTER_CLOCK_GDK (clutter_master_clock_gdk_get_type ())
#define CLUTTER_MASTER_CLOCK_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK_GDK, ClutterMasterClockGdk))
#define CLUTTER_IS_MASTER_CLOCK_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK_GDK))
#define CLUTTER_MASTER_CLOCK_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MASTER_CLOCK_GDK, ClutterMasterClockGdkClass))
typedef struct _ClutterMasterClockGdk ClutterMasterClockGdk;
typedef struct _ClutterMasterClockGdkClass ClutterMasterClockGdkClass;
struct _ClutterMasterClockGdkClass
{
GObjectClass parent_class;
};
GType clutter_master_clock_gdk_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __CLUTTER_MASTER_CLOCK_GDK_H__ */

View File

@ -1,29 +0,0 @@
#ifndef __CLUTTER_SETTINGS_GDK_H__
#define __CLUTTER_SETTINGS_GDK_H__
/* XSETTINGS key names to ClutterSettings properties */
static const struct {
const char *gdk_setting_name;
const char *settings_property;
GType type;
} _clutter_settings_map[] = {
{ "gdk-window-scaling-factor", "window-scaling-factor", G_TYPE_INT },
{ "gtk-double-click-time", "double-click-time", G_TYPE_INT },
{ "gtk-double-click-distance", "double-click-distance", G_TYPE_INT },
{ "gtk-dnd-drag-threshold", "dnd-drag-threshold", G_TYPE_INT },
{ "gtk-font-name", "font-name", G_TYPE_STRING },
{ "gtk-xft-antialias", "font-antialias", G_TYPE_INT },
{ "gtk-xft-dpi", "font-dpi", G_TYPE_INT },
{ "gtk-xft-hinting", "font-hinting", G_TYPE_INT },
{ "gtk-xft-hintstyle", "font-hint-style", G_TYPE_STRING },
{ "gtk-xft-rgba", "font-subpixel-order", G_TYPE_STRING },
{ "gtk-fontconfig-timestamp", "fontconfig-timestamp", G_TYPE_UINT },
};
static const gint _n_clutter_settings_map = G_N_ELEMENTS (_clutter_settings_map);
#define CLUTTER_SETTING_TYPE(id) (_clutter_settings_map[(id)].type)
#define CLUTTER_SETTING_GDK_NAME(id) (_clutter_settings_map[(id)].gdk_setting_name)
#define CLUTTER_SETTING_PROPERTY(id) (_clutter_settings_map[(id)].settings_property)
#endif /* __CLUTTER_SETTINGS_GDK_H__ */

View File

@ -1,933 +0,0 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
* Authored By Matthew Allum <mallum@openedhand.com>
* Copyright (C) 2006-2007 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#include "config.h"
#include <math.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <cogl/cogl.h>
#ifdef COGL_HAS_XLIB_SUPPORT
#include <cogl/cogl-xlib.h>
#endif
#define GDK_DISABLE_DEPRECATION_WARNINGS
#include <gdk/gdk.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
#include "clutter-backend-gdk.h"
#include "clutter-stage-gdk.h"
#include "clutter-gdk.h"
#include "clutter-actor-private.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-enum-types.h"
#include "clutter-event-translator.h"
#include "clutter-event-private.h"
#include "clutter-feature.h"
#include "clutter-main.h"
#include "clutter-paint-volume-private.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
#define clutter_stage_gdk_get_type _clutter_stage_gdk_get_type
G_DEFINE_TYPE_WITH_CODE (ClutterStageGdk,
clutter_stage_gdk,
CLUTTER_TYPE_STAGE_COGL,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
static void
clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data)
{
ClutterStageGdk *stage_gdk = user_data;
/* we assume that a GDK event mask is bitwise compatible with X11
event masks */
gdk_window_set_events (stage_gdk->window, event_mask | CLUTTER_STAGE_GDK_EVENT_MASK);
}
#endif
static void
clutter_stage_gdk_set_gdk_geometry (ClutterStageGdk *stage)
{
GdkGeometry geometry;
ClutterStage *wrapper = CLUTTER_STAGE_COGL (stage)->wrapper;
gboolean resize = clutter_stage_get_user_resizable (wrapper);
if (!resize)
{
geometry.min_width = geometry.max_width = gdk_window_get_width (stage->window);
geometry.min_height = geometry.max_height = gdk_window_get_height (stage->window);
gdk_window_set_geometry_hints (stage->window,
&geometry,
GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
}
else
{
clutter_stage_get_minimum_size (wrapper,
(guint *)&geometry.min_width,
(guint *)&geometry.min_height);
gdk_window_set_geometry_hints (stage->window,
&geometry,
GDK_HINT_MIN_SIZE);
}
}
static void
clutter_stage_gdk_get_geometry (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *geometry)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
geometry->x = geometry->y = 0;
if (stage_gdk->window != NULL)
{
geometry->width = gdk_window_get_width (stage_gdk->window);
geometry->height = gdk_window_get_height (stage_gdk->window);
}
else
{
geometry->width = 800;
geometry->height = 600;
}
}
static void
clutter_stage_gdk_resize (ClutterStageWindow *stage_window,
gint width,
gint height)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (width == 0 || height == 0)
{
/* Should not happen, if this turns up we need to debug it and
* determine the cleanest way to fix.
*/
g_warning ("GDK stage not allowed to have 0 width or height");
width = 1;
height = 1;
}
CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height);
/* No need to resize foreign windows, it should be handled by the
* embedding framework, but on wayland we might need to resize our
* own subsurface.
*/
if (!stage_gdk->foreign_window)
gdk_window_resize (stage_gdk->window, width, height);
#if defined(GDK_WINDOWING_WAYLAND) && defined(COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
else if (GDK_IS_WAYLAND_WINDOW (stage_gdk->window))
{
int scale = gdk_window_get_scale_factor (stage_gdk->window);
cogl_wayland_onscreen_resize (CLUTTER_STAGE_COGL (stage_gdk)->onscreen,
width * scale, height * scale, 0, 0);
}
#endif
}
static void
clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window != NULL)
{
g_object_set_data (G_OBJECT (stage_gdk->window),
"clutter-stage-window", NULL);
if (stage_gdk->foreign_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
g_object_unref (stage_gdk->window);
/* Clutter still uses part of the deprecated stateful API of
* Cogl (in particulart cogl_set_framebuffer). It means Cogl
* can keep an internal reference to the onscreen object we
* rendered to. In the case of foreign window, we want to
* avoid this, as we don't know what's going to happen to
* that window.
*
* The following call sets the current Cogl framebuffer to a
* dummy 1x1 one if we're unrealizing the current one, so
* Cogl doesn't keep any reference to the foreign window.
*/
if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_cogl->onscreen))
_clutter_backend_reset_cogl_framebuffer (stage_cogl->backend);
}
else
gdk_window_destroy (stage_gdk->window);
stage_gdk->window = NULL;
}
clutter_stage_window_parent_iface->unrealize (stage_window);
#if defined(GDK_WINDOWING_WAYLAND)
g_clear_pointer (&stage_gdk->subsurface, wl_subsurface_destroy);
g_clear_pointer (&stage_gdk->clutter_surface, wl_surface_destroy);
#endif
}
#if defined(GDK_WINDOWING_WAYLAND)
static struct wl_surface *
clutter_stage_gdk_wayland_surface (ClutterStageGdk *stage_gdk)
{
GdkDisplay *display;
struct wl_compositor *compositor;
struct wl_surface *parent_surface;
struct wl_region *input_region;
gint x, y;
if (!stage_gdk->foreign_window ||
gdk_window_get_window_type (stage_gdk->window) != GDK_WINDOW_CHILD)
return gdk_wayland_window_get_wl_surface (stage_gdk->window);
if (stage_gdk->clutter_surface)
return stage_gdk->clutter_surface;
/* On Wayland if we render to a foreign window, we setup our own
* surface to not render in the same buffers as the embedding
* framework.
*/
display = gdk_display_get_default ();
compositor = gdk_wayland_display_get_wl_compositor (display);
stage_gdk->clutter_surface = wl_compositor_create_surface (compositor);
/* Since we run inside GDK, we can let the embedding framework
* dispatch the events to Clutter. For that to happen we need to
* disable input on our surface. */
input_region = wl_compositor_create_region (compositor);
wl_region_add (input_region, 0, 0, 0, 0);
wl_surface_set_input_region (stage_gdk->clutter_surface, input_region);
wl_region_destroy (input_region);
wl_surface_set_buffer_scale (stage_gdk->clutter_surface,
gdk_window_get_scale_factor (stage_gdk->window));
parent_surface = gdk_wayland_window_get_wl_surface (gdk_window_get_toplevel (stage_gdk->window));
stage_gdk->subsurface = wl_subcompositor_get_subsurface (stage_gdk->subcompositor,
stage_gdk->clutter_surface,
parent_surface);
gdk_window_get_origin (stage_gdk->window, &x, &y);
wl_subsurface_set_position (stage_gdk->subsurface, x, y);
wl_subsurface_set_desync (stage_gdk->subsurface);
return stage_gdk->clutter_surface;
}
#endif
void
_clutter_stage_gdk_notify_configure (ClutterStageGdk *stage_gdk,
gint x,
gint y,
gint width,
gint height)
{
if (x < 0 || y < 0 || width < 1 || height < 1)
return;
if (stage_gdk->foreign_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_gdk);
int scale = gdk_window_get_scale_factor (stage_gdk->window);
#if defined(GDK_WINDOWING_WAYLAND) && defined(COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
if (GDK_IS_WAYLAND_WINDOW (stage_gdk->window) &&
gdk_window_get_window_type (stage_gdk->window) == GDK_WINDOW_CHILD &&
stage_gdk->subsurface)
{
gint rx, ry;
gdk_window_get_origin (stage_gdk->window, &rx, &ry);
wl_subsurface_set_position (stage_gdk->subsurface, rx, ry);
wl_surface_set_buffer_scale (stage_gdk->clutter_surface, scale);
cogl_wayland_onscreen_resize (stage_cogl->onscreen,
width * scale, height * scale, 0, 0);
}
else
#endif
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_WINDOW (stage_gdk->window))
{
ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
XConfigureEvent xevent = { ConfigureNotify };
xevent.window = GDK_WINDOW_XID (stage_gdk->window);
xevent.width = width * scale;
xevent.height = height * scale;
/* Ensure cogl knows about the new size immediately, as we will
* draw before we get the ConfigureNotify response. */
cogl_xlib_renderer_handle_event (backend->cogl_renderer, (XEvent *)&xevent);
}
else
#endif
{
/* Currently we only support X11 and Wayland. */
g_assert_not_reached();
}
}
}
static gboolean
clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
GdkWindowAttr attributes;
gboolean cursor_visible;
gboolean use_alpha;
gfloat width, height;
int scale;
if (backend->cogl_context == NULL)
{
g_warning ("Missing Cogl context: was Clutter correctly initialized?");
return FALSE;
}
if (!stage_gdk->foreign_window)
{
if (stage_gdk->window != NULL)
{
/* complete realizing the stage */
cairo_rectangle_int_t geometry;
clutter_stage_gdk_get_geometry (stage_window, &geometry);
clutter_actor_set_size (CLUTTER_ACTOR (stage_cogl->wrapper),
geometry.width,
geometry.height);
gdk_window_ensure_native (stage_gdk->window);
gdk_window_set_events (stage_gdk->window, CLUTTER_STAGE_GDK_EVENT_MASK);
return TRUE;
}
else
{
attributes.title = NULL;
g_object_get (stage_cogl->wrapper,
"cursor-visible", &cursor_visible,
"title", &attributes.title,
"width", &width,
"height", &height,
"use-alpha", &use_alpha,
NULL);
attributes.width = width;
attributes.height = height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.window_type = GDK_WINDOW_TOPLEVEL;
attributes.event_mask = CLUTTER_STAGE_GDK_EVENT_MASK;
attributes.cursor = NULL;
if (!cursor_visible)
{
if (stage_gdk->blank_cursor == NULL)
stage_gdk->blank_cursor = gdk_cursor_new_for_display (backend_gdk->display, GDK_BLANK_CURSOR);
attributes.cursor = stage_gdk->blank_cursor;
}
/* If the ClutterStage:use-alpha is set, but GDK does not have an
* RGBA visual, then we unset the property on the Stage
*/
if (use_alpha)
{
if (gdk_screen_get_rgba_visual (backend_gdk->screen) == NULL)
{
clutter_stage_set_use_alpha (stage_cogl->wrapper, FALSE);
use_alpha = FALSE;
}
}
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_DISPLAY (backend_gdk->display))
{
XVisualInfo *xvisinfo = cogl_clutter_winsys_xlib_get_visual_info ();
if (xvisinfo != NULL)
{
attributes.visual = gdk_x11_screen_lookup_visual (backend_gdk->screen,
xvisinfo->visualid);
}
}
else
#endif
{
attributes.visual = use_alpha
? gdk_screen_get_rgba_visual (backend_gdk->screen)
: gdk_screen_get_system_visual (backend_gdk->screen);
}
if (attributes.visual == NULL)
{
/* This could still be an RGBA visual, although normally it's not */
attributes.visual = gdk_screen_get_system_visual (backend_gdk->screen);
}
stage_gdk->foreign_window = FALSE;
stage_gdk->window = gdk_window_new (NULL, &attributes,
GDK_WA_TITLE | GDK_WA_CURSOR | GDK_WA_VISUAL);
g_free (attributes.title);
}
clutter_stage_gdk_set_gdk_geometry (stage_gdk);
gdk_window_ensure_native (stage_gdk->window);
}
else
{
width = gdk_window_get_width (stage_gdk->window);
height = gdk_window_get_height (stage_gdk->window);
}
g_object_set_data (G_OBJECT (stage_gdk->window), "clutter-stage-window", stage_gdk);
scale = gdk_window_get_scale_factor (stage_gdk->window);
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
width * scale, height * scale);
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_WINDOW (stage_gdk->window))
{
cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
GDK_WINDOW_XID (stage_gdk->window),
clutter_stage_gdk_update_foreign_event_mask,
stage_gdk);
}
else
#endif
#if defined(GDK_WINDOWING_WAYLAND) && defined(COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
if (GDK_IS_WAYLAND_WINDOW (stage_gdk->window))
{
cogl_wayland_onscreen_set_foreign_surface (stage_cogl->onscreen,
clutter_stage_gdk_wayland_surface (stage_gdk));
}
else
#endif
{
g_warning ("Cannot find an appropriate CoglWinsys for a "
"GdkWindow of type %s", G_OBJECT_TYPE_NAME (stage_gdk->window));
cogl_object_unref (stage_cogl->onscreen);
stage_cogl->onscreen = NULL;
if (!stage_gdk->foreign_window)
gdk_window_destroy (stage_gdk->window);
stage_gdk->window = NULL;
return FALSE;
}
return clutter_stage_window_parent_iface->realize (stage_window);
}
static void
clutter_stage_gdk_set_fullscreen (ClutterStageWindow *stage_window,
gboolean is_fullscreen)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterStage *stage = CLUTTER_STAGE_COGL (stage_window)->wrapper;
gboolean swap_throttle;
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
return;
if (stage_gdk->window == NULL || stage_gdk->foreign_window)
return;
CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un");
if (is_fullscreen)
gdk_window_fullscreen (stage_gdk->window);
else
gdk_window_unfullscreen (stage_gdk->window);
/* Full-screen stages are usually unredirected to improve performance
* by avoiding a copy; when that happens, we need to turn back swap
* throttling because we won't be managed by the compositor any more,
*/
swap_throttle = is_fullscreen;
#ifdef GDK_WINDOWING_WAYLAND
{
/* Except on Wayland, where there's a deadlock due to both Cogl
* and GDK attempting to consume the throttling event; see bug
* https://bugzilla.gnome.org/show_bug.cgi?id=754671#c1
*/
GdkDisplay *display = clutter_gdk_get_default_display ();
if (GDK_IS_WAYLAND_DISPLAY (display))
swap_throttle = FALSE;
}
#endif
cogl_onscreen_set_swap_throttled (stage_cogl->onscreen, swap_throttle);
}
static void
clutter_stage_gdk_set_cursor_visible (ClutterStageWindow *stage_window,
gboolean cursor_visible)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window == NULL)
return;
if (cursor_visible)
{
gdk_window_set_cursor (stage_gdk->window, NULL);
}
else
{
if (stage_gdk->blank_cursor == NULL)
{
GdkDisplay *display = clutter_gdk_get_default_display ();
stage_gdk->blank_cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
}
gdk_window_set_cursor (stage_gdk->window, stage_gdk->blank_cursor);
}
}
static void
clutter_stage_gdk_set_title (ClutterStageWindow *stage_window,
const gchar *title)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window == NULL || stage_gdk->foreign_window)
return;
gdk_window_set_title (stage_gdk->window, title);
}
static void
clutter_stage_gdk_set_user_resizable (ClutterStageWindow *stage_window,
gboolean is_resizable)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
GdkWMFunction function;
if (stage_gdk->window == NULL || stage_gdk->foreign_window)
return;
function = GDK_FUNC_MOVE | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE;
if (is_resizable)
function |= GDK_FUNC_RESIZE | GDK_FUNC_MAXIMIZE;
gdk_window_set_functions (stage_gdk->window, function);
clutter_stage_gdk_set_gdk_geometry (stage_gdk);
}
static void
clutter_stage_gdk_set_accept_focus (ClutterStageWindow *stage_window,
gboolean accept_focus)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window == NULL || stage_gdk->foreign_window)
return;
gdk_window_set_accept_focus (stage_gdk->window, accept_focus);
}
static void
clutter_stage_gdk_show (ClutterStageWindow *stage_window,
gboolean do_raise)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
g_return_if_fail (stage_gdk->window != NULL);
clutter_actor_map (CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_gdk)->wrapper));
/* Foreign window should be shown by the embedding framework. */
if (!stage_gdk->foreign_window)
{
if (do_raise)
gdk_window_show (stage_gdk->window);
else
gdk_window_show_unraised (stage_gdk->window);
}
}
static void
clutter_stage_gdk_hide (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
g_return_if_fail (stage_gdk->window != NULL);
clutter_actor_unmap (CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_gdk)->wrapper));
/* Foreign window should be hidden by the embedding framework. */
if (!stage_gdk->foreign_window)
gdk_window_hide (stage_gdk->window);
}
static gboolean
clutter_stage_gdk_can_clip_redraws (ClutterStageWindow *stage_window)
{
return TRUE;
}
static int
clutter_stage_gdk_get_scale_factor (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window == NULL)
return 1;
return gdk_window_get_scale_factor (stage_gdk->window);
}
static void
clutter_stage_gdk_redraw (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
GdkFrameClock *clock;
if (stage_gdk->window == NULL ||
(clock = gdk_window_get_frame_clock (stage_gdk->window)) == NULL)
{
clutter_stage_window_parent_iface->redraw (stage_window);
return;
}
gdk_frame_clock_begin_updating (clock);
clutter_stage_window_parent_iface->redraw (stage_window);
gdk_frame_clock_end_updating (clock);
}
static void
clutter_stage_gdk_schedule_update (ClutterStageWindow *stage_window,
gint sync_delay)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
GdkFrameClock *clock;
if (stage_gdk->window == NULL ||
(clock = gdk_window_get_frame_clock (stage_gdk->window)) == NULL)
{
clutter_stage_window_parent_iface->schedule_update (stage_window, sync_delay);
return;
}
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_PAINT);
clutter_stage_window_parent_iface->schedule_update (stage_window, sync_delay);
}
static gint64
clutter_stage_gdk_get_update_time (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
GdkFrameClock *frame_clock;
GdkFrameTimings *frame_timings;
if (stage_gdk->window == NULL ||
(frame_clock = gdk_window_get_frame_clock (stage_gdk->window)) == NULL ||
(frame_timings = gdk_frame_clock_get_current_timings (frame_clock)) == NULL ||
!gdk_frame_timings_get_complete (frame_timings))
return -1; /* No data, indefinite */
return (gdk_frame_timings_get_presentation_time (frame_timings) +
gdk_frame_timings_get_refresh_interval (frame_timings));
}
static void
clutter_stage_gdk_dispose (GObject *gobject)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (gobject);
if (stage_gdk->window != NULL)
{
g_object_set_data (G_OBJECT (stage_gdk->window),
"clutter-stage-window", NULL);
if (stage_gdk->foreign_window)
g_object_unref (stage_gdk->window);
else
gdk_window_destroy (stage_gdk->window);
stage_gdk->window = NULL;
}
if (stage_gdk->blank_cursor != NULL)
{
g_object_unref (stage_gdk->blank_cursor);
stage_gdk->blank_cursor = NULL;
}
G_OBJECT_CLASS (clutter_stage_gdk_parent_class)->dispose (gobject);
}
static void
clutter_stage_gdk_class_init (ClutterStageGdkClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = clutter_stage_gdk_dispose;
}
#if defined(GDK_WINDOWING_WAYLAND)
static void
registry_handle_global (void *data,
struct wl_registry *registry,
uint32_t name,
const char *interface,
uint32_t version)
{
ClutterStageGdk *stage_gdk = data;
if (strcmp (interface, "wl_subcompositor") == 0)
{
stage_gdk->subcompositor = wl_registry_bind (registry,
name,
&wl_subcompositor_interface,
1);
}
}
static void
registry_handle_global_remove (void *data,
struct wl_registry *registry,
uint32_t name)
{
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global,
registry_handle_global_remove
};
#endif
static void
clutter_stage_gdk_init (ClutterStageGdk *stage)
{
#if defined(GDK_WINDOWING_WAYLAND)
{
GdkDisplay *gdk_display = gdk_display_get_default ();
if (GDK_IS_WAYLAND_DISPLAY (gdk_display))
{
struct wl_display *display;
struct wl_registry *registry;
display = gdk_wayland_display_get_wl_display (gdk_display);
registry = wl_display_get_registry (display);
wl_registry_add_listener (registry, &registry_listener, stage);
wl_display_roundtrip (display);
}
}
#endif
}
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
iface->set_title = clutter_stage_gdk_set_title;
iface->set_fullscreen = clutter_stage_gdk_set_fullscreen;
iface->set_cursor_visible = clutter_stage_gdk_set_cursor_visible;
iface->set_user_resizable = clutter_stage_gdk_set_user_resizable;
iface->set_accept_focus = clutter_stage_gdk_set_accept_focus;
iface->show = clutter_stage_gdk_show;
iface->hide = clutter_stage_gdk_hide;
iface->resize = clutter_stage_gdk_resize;
iface->get_geometry = clutter_stage_gdk_get_geometry;
iface->realize = clutter_stage_gdk_realize;
iface->unrealize = clutter_stage_gdk_unrealize;
iface->can_clip_redraws = clutter_stage_gdk_can_clip_redraws;
iface->get_scale_factor = clutter_stage_gdk_get_scale_factor;
iface->redraw = clutter_stage_gdk_redraw;
iface->schedule_update = clutter_stage_gdk_schedule_update;
iface->get_update_time = clutter_stage_gdk_get_update_time;
}
/**
* clutter_gdk_get_stage_window:
* @stage: a #ClutterStage
*
* Gets the stages GdkWindow.
*
* Return value: (transfer none): A GdkWindow* for the stage window.
*
* Since: 1.10
*/
GdkWindow *
clutter_gdk_get_stage_window (ClutterStage *stage)
{
ClutterStageWindow *impl;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
impl = _clutter_stage_get_window (stage);
if (!CLUTTER_IS_STAGE_GDK (impl))
{
g_critical ("The Clutter backend is not a GDK backend");
return NULL;
}
return CLUTTER_STAGE_GDK (impl)->window;
}
/**
* clutter_gdk_get_stage_from_window:
* @window: a #GtkWindow
*
* Gets the stage for a particular X window.
*
* Return value: (transfer none): A #ClutterStage, or% NULL if a stage
* does not exist for the window
*
* Since: 1.10
*/
ClutterStage *
clutter_gdk_get_stage_from_window (GdkWindow *window)
{
ClutterStageGdk *stage_gdk = g_object_get_data (G_OBJECT (window), "clutter-stage-window");
if (stage_gdk != NULL && CLUTTER_IS_STAGE_GDK (stage_gdk))
return CLUTTER_STAGE_COGL (stage_gdk)->wrapper;
return NULL;
}
typedef struct
{
ClutterStageGdk *stage_gdk;
GdkWindow *window;
} ForeignWindowClosure;
static void
set_foreign_window_callback (ClutterActor *actor,
void *data)
{
ForeignWindowClosure *closure = data;
ClutterStageGdk *stage_gdk = closure->stage_gdk;
stage_gdk->window = closure->window;
stage_gdk->foreign_window = TRUE;
/* calling this with the stage unrealized will unset the stage
* from the GL context; once the stage is realized the GL context
* will be set again
*/
clutter_stage_ensure_current (CLUTTER_STAGE (actor));
}
/**
* clutter_gdk_set_stage_foreign:
* @stage: a #ClutterStage
* @window: an existing #GdkWindow
*
* Target the #ClutterStage to use an existing external #GdkWindow
*
* Return value: %TRUE if foreign window is valid
*
* Since: 1.10
*/
gboolean
clutter_gdk_set_stage_foreign (ClutterStage *stage,
GdkWindow *window)
{
ForeignWindowClosure closure;
ClutterStageGdk *stage_gdk;
ClutterStageWindow *impl;
ClutterActor *actor;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
g_return_val_if_fail (!CLUTTER_ACTOR_IN_DESTRUCTION (stage), FALSE);
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
impl = _clutter_stage_get_window (stage);
if (!CLUTTER_IS_STAGE_GDK (impl))
{
g_critical ("The Clutter backend is not a GDK backend");
return FALSE;
}
stage_gdk = CLUTTER_STAGE_GDK (impl);
if (g_object_get_data (G_OBJECT (window), "clutter-stage-window") != NULL)
{
g_critical ("The provided GdkWindow is already in use by another ClutterStage");
return FALSE;
}
closure.stage_gdk = stage_gdk;
closure.window = g_object_ref (window);
actor = CLUTTER_ACTOR (stage);
_clutter_actor_rerealize (actor,
set_foreign_window_callback,
&closure);
/* Queue a relayout - so the stage will be allocated the new
* window size.
*
* Note also that when the stage gets allocated the new
* window size that will result in the stage's
* priv->viewport being changed, which will in turn result
* in the Cogl viewport changing when _clutter_do_redraw
* calls _clutter_stage_maybe_setup_viewport().
*/
clutter_actor_queue_relayout (actor);
return TRUE;
}

View File

@ -1,95 +0,0 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
* Authored By Matthew Allum <mallum@openedhand.com>
* Copyright (C) 2006-2007 OpenedHand
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __CLUTTER_STAGE_GDK_H__
#define __CLUTTER_STAGE_GDK_H__
#include <clutter/clutter-group.h>
#include <clutter/clutter-stage.h>
#include <gdk/gdk.h>
#include "clutter-backend-gdk.h"
#include "cogl/clutter-stage-cogl.h"
G_BEGIN_DECLS
#define CLUTTER_TYPE_STAGE_GDK (_clutter_stage_gdk_get_type ())
#define CLUTTER_STAGE_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_GDK, ClutterStageGdk))
#define CLUTTER_IS_STAGE_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_GDK))
#define CLUTTER_STAGE_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_GDK, ClutterStageGdkClass))
#define CLUTTER_IS_STAGE_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_GDK))
#define CLUTTER_STAGE_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_GDK, ClutterStageGdkClass))
typedef struct _ClutterStageGdk ClutterStageGdk;
typedef struct _ClutterStageGdkClass ClutterStageGdkClass;
struct _ClutterStageGdk
{
ClutterStageCogl parent_instance;
GdkWindow *window;
GdkCursor *blank_cursor;
gboolean foreign_window;
#if defined(GDK_WINDOWING_WAYLAND)
struct wl_subcompositor *subcompositor;
struct wl_surface *clutter_surface;
struct wl_subsurface *subsurface;
#endif
};
struct _ClutterStageGdkClass
{
ClutterStageCoglClass parent_class;
};
#define CLUTTER_STAGE_GDK_EVENT_MASK \
(GDK_STRUCTURE_MASK | \
GDK_FOCUS_CHANGE_MASK | \
GDK_EXPOSURE_MASK | \
GDK_PROPERTY_CHANGE_MASK | \
GDK_ENTER_NOTIFY_MASK | \
GDK_LEAVE_NOTIFY_MASK | \
GDK_KEY_PRESS_MASK | \
GDK_KEY_RELEASE_MASK | \
GDK_BUTTON_PRESS_MASK | \
GDK_BUTTON_RELEASE_MASK | \
GDK_POINTER_MOTION_MASK | \
GDK_TOUCH_MASK | \
GDK_SCROLL_MASK)
GType _clutter_stage_gdk_get_type (void) G_GNUC_CONST;
void _clutter_stage_gdk_notify_configure (ClutterStageGdk *stage_gdk,
gint x,
gint y,
gint width,
gint height);
void _clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data);
G_END_DECLS
#endif /* __CLUTTER_STAGE_H__ */

View File

@ -214,10 +214,6 @@ AC_ARG_ENABLE([x11-backend],
[AS_HELP_STRING([--enable-x11-backend=@<:@yes/no@:>@], [Enable the X11 backend (default=check)])],
[enable_x11=$enableval],
[enable_x11=check])
AC_ARG_ENABLE([gdk-backend],
[AS_HELP_STRING([--enable-gdk-backend=@<:@yes/no@:>@], [Enable the GDK backend (default=check)])],
[enable_gdk=$enableval],
[enable_gdk=check])
AC_ARG_ENABLE([wayland-backend],
[AS_HELP_STRING([--enable-wayland-backend=@<:@yes/no@:>@], [Enable the Wayland client backend (default=check)])],
[enable_wayland=$enableval],
@ -242,10 +238,6 @@ AS_IF([test "x$enable_x11" = xcheck], [
PKG_CHECK_EXISTS([x11], [enable_x11=yes], [enable_x11=no])
])
AS_IF([test "x$enable_gdk" = xcheck], [
PKG_CHECK_EXISTS([gdk-3.0 >= gdk_req_version], [enable_gdk=yes], [enable_gdk=no])
])
AS_IF([test "x$enable_egl" = xcheck], [
PKG_CHECK_EXISTS([egl], [enable_egl=yes], [enable_egl=no])
PKG_CHECK_EXISTS([libinput], [enable_evdev=yes], [enable_evdev=no])
@ -272,17 +264,6 @@ AS_IF([test "x$enable_x11" = "xyes"],
[])
])
AS_IF([test "x$enable_gdk" = "xyes"],
[
CLUTTER_BACKENDS="$CLUTTER_BACKENDS gdk"
CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS gdk"
SUPPORT_GDK=1
SUPPORT_COGL=1
BACKEND_PC_FILES="$BACKEND_PC_FILES gdk-3.0"
])
AS_IF([test "x$enable_wayland" != xno],
[
# We need to manually check for Wayland support in Cogl because
@ -401,7 +382,6 @@ AS_IF([test "x$enable_evdev" = xyes], [
# conditionals for use in automake files...
AM_CONDITIONAL(SUPPORT_GLX, [test "x$SUPPORT_GLX" = "x1"])
AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "x1"])
AM_CONDITIONAL(SUPPORT_GDK, [test "x$SUPPORT_GDK" = "x1"])
AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "x1"])
AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$SUPPORT_WAYLAND" = "x1"])
@ -441,10 +421,6 @@ AS_IF([test "x$SUPPORT_X11" = "x1"],
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
#define CLUTTER_WINDOWING_X11 \"x11\"
#define CLUTTER_INPUT_X11 \"x11\""])
AS_IF([test "x$SUPPORT_GDK" = "x1"],
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
#define CLUTTER_WINDOWING_GDK \"gdk\"
#define CLUTTER_INPUT_GDK \"gdk\""])
AS_IF([test "x$SUPPORT_GLX" = "x1"],
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
#define CLUTTER_WINDOWING_GLX \"glx\""])