mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 11:32:04 +00:00
gdk: drop gdk backend
This commit is contained in:
parent
0777de1757
commit
04c84b049f
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
@ -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__ */
|
@ -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);
|
||||
}
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -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__ */
|
@ -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, ®istry_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;
|
||||
}
|
@ -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__ */
|
24
configure.ac
24
configure.ac
@ -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\""])
|
||||
|
Loading…
Reference in New Issue
Block a user