clutter: add Mir windowing/input backend
Added support for Mir, now clutter can natively draw on MirSurfaces. This depends on latest cogl git. Run your clutter apps using CLUTTER_BACKEND=mir Signed-off-by: Emmanuele Bassi <ebassi@gnome.org>
This commit is contained in:
parent
10cce00440
commit
77db999339
@ -699,6 +699,33 @@ clutter-wayland-compositor-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERS
|
|||||||
pc_files += clutter-wayland-compositor-$(CLUTTER_API_VERSION).pc
|
pc_files += clutter-wayland-compositor-$(CLUTTER_API_VERSION).pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Mir backend rules
|
||||||
|
if SUPPORT_MIR
|
||||||
|
backend_source_h_priv += \
|
||||||
|
mir/clutter-backend-mir.h \
|
||||||
|
mir/clutter-backend-mir-priv.h \
|
||||||
|
mir/clutter-stage-mir.h \
|
||||||
|
mir/clutter-event-mir.h \
|
||||||
|
mir/clutter-input-device-mir.h \
|
||||||
|
mir/clutter-device-manager-mir.h
|
||||||
|
|
||||||
|
backend_source_c += \
|
||||||
|
mir/clutter-backend-mir.c \
|
||||||
|
mir/clutter-stage-mir.c \
|
||||||
|
mir/clutter-event-mir.c \
|
||||||
|
mir/clutter-input-device-mir.c \
|
||||||
|
mir/clutter-device-manager-mir.c
|
||||||
|
|
||||||
|
|
||||||
|
cluttermir_includedir = $(clutter_includedir)/mir
|
||||||
|
cluttermir_include_HEADERS = $(srcdir)/mir/clutter-mir.h
|
||||||
|
|
||||||
|
clutter-mir-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc
|
||||||
|
$(QUIET_GEN)cp -f $< $(@F)
|
||||||
|
|
||||||
|
pc_files += clutter-mir-$(CLUTTER_API_VERSION).pc
|
||||||
|
endif # SUPPORT_MIR
|
||||||
|
|
||||||
if SUPPORT_EGL
|
if SUPPORT_EGL
|
||||||
backend_source_h += $(egl_source_h)
|
backend_source_h += $(egl_source_h)
|
||||||
backend_source_c += $(egl_source_c)
|
backend_source_c += $(egl_source_c)
|
||||||
@ -898,7 +925,7 @@ clutter.vsenums_h:
|
|||||||
echo 'perl %1\bin\glib-mkenums --template ../../clutter/clutter-enum-types.h.in ' >vsenums_h.temp1
|
echo 'perl %1\bin\glib-mkenums --template ../../clutter/clutter-enum-types.h.in ' >vsenums_h.temp1
|
||||||
for F in `echo $(source_h) $(backend_source_h) $(srcdir)/win32/clutter-win32.h`; do \
|
for F in `echo $(source_h) $(backend_source_h) $(srcdir)/win32/clutter-win32.h`; do \
|
||||||
case $$F in \
|
case $$F in \
|
||||||
*-x11*.h|*-wayland*.h|*-gdk*.h|*-glx*.h|*-cex*.h|*-egl*.h|*-osx*.h) ;; \
|
*-x11*.h|*-wayland*.h|*-gdk*.h|*-glx*.h|*-cex*.h|*-egl*.h|*-osx*.h|*-mir*.h) ;; \
|
||||||
*.h) echo '../../clutter'$$F' ' \
|
*.h) echo '../../clutter'$$F' ' \
|
||||||
;; \
|
;; \
|
||||||
esac; \
|
esac; \
|
||||||
@ -913,7 +940,7 @@ clutter.vsenums_c:
|
|||||||
echo 'perl %1\bin\glib-mkenums --template ../../clutter/clutter-enum-types.c.in ' >vsenums_c.temp1
|
echo 'perl %1\bin\glib-mkenums --template ../../clutter/clutter-enum-types.c.in ' >vsenums_c.temp1
|
||||||
for F in `echo $(source_h) $(backend_source_h) $(srcdir)/win32/clutter-win32.h`; do \
|
for F in `echo $(source_h) $(backend_source_h) $(srcdir)/win32/clutter-win32.h`; do \
|
||||||
case $$F in \
|
case $$F in \
|
||||||
*-x11*.h|*-wayland*.h|*-gdk*.h|*-glx*.h|*-cex*.h|*-egl*.h|*-osx*.h) ;; \
|
*-x11*.h|*-wayland*.h|*-gdk*.h|*-glx*.h|*-cex*.h|*-egl*.h|*-osx*.h|*-mir*.h) ;; \
|
||||||
*.h) echo '../../clutter'$$F' ' \
|
*.h) echo '../../clutter'$$F' ' \
|
||||||
;; \
|
;; \
|
||||||
esac; \
|
esac; \
|
||||||
|
@ -89,6 +89,12 @@
|
|||||||
#ifdef CLUTTER_INPUT_WAYLAND
|
#ifdef CLUTTER_INPUT_WAYLAND
|
||||||
#include "wayland/clutter-device-manager-wayland.h"
|
#include "wayland/clutter-device-manager-wayland.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CLUTTER_WINDOWING_MIR
|
||||||
|
#include "mir/clutter-backend-mir.h"
|
||||||
|
#endif
|
||||||
|
#ifdef CLUTTER_INPUT_MIR
|
||||||
|
#include "mir/clutter-device-manager-mir.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CLUTTER_WAYLAND_COMPOSITOR
|
#ifdef HAVE_CLUTTER_WAYLAND_COMPOSITOR
|
||||||
#include <cogl/cogl-wayland-server.h>
|
#include <cogl/cogl-wayland-server.h>
|
||||||
@ -510,6 +516,11 @@ _clutter_create_backend (void)
|
|||||||
if (backend == NULL || backend == I_(CLUTTER_WINDOWING_EGL))
|
if (backend == NULL || backend == I_(CLUTTER_WINDOWING_EGL))
|
||||||
retval = g_object_new (CLUTTER_TYPE_BACKEND_EGL_NATIVE, NULL);
|
retval = g_object_new (CLUTTER_TYPE_BACKEND_EGL_NATIVE, NULL);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef CLUTTER_WINDOWING_MIR
|
||||||
|
if (backend == NULL || backend == I_(CLUTTER_WINDOWING_MIR))
|
||||||
|
retval = g_object_new (CLUTTER_TYPE_BACKEND_MIR, NULL);
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
if (backend == NULL)
|
if (backend == NULL)
|
||||||
g_error ("No default Clutter backend found.");
|
g_error ("No default Clutter backend found.");
|
||||||
@ -589,6 +600,14 @@ clutter_backend_real_init_events (ClutterBackend *backend)
|
|||||||
_clutter_events_wayland_init (backend);
|
_clutter_events_wayland_init (backend);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef CLUTTER_INPUT_MIR
|
||||||
|
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_MIR) &&
|
||||||
|
(input_backend == NULL || input_backend == I_(CLUTTER_INPUT_MIR)))
|
||||||
|
{
|
||||||
|
_clutter_events_mir_init (backend);
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
if (input_backend != NULL)
|
if (input_backend != NULL)
|
||||||
{
|
{
|
||||||
|
@ -89,6 +89,9 @@
|
|||||||
#ifdef CLUTTER_WINDOWING_WAYLAND
|
#ifdef CLUTTER_WINDOWING_WAYLAND
|
||||||
#include "wayland/clutter-backend-wayland.h"
|
#include "wayland/clutter-backend-wayland.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CLUTTER_WINDOWING_MIR
|
||||||
|
#include "mir/clutter-backend-mir.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
#include <cogl-pango/cogl-pango.h>
|
#include <cogl-pango/cogl-pango.h>
|
||||||
@ -3781,6 +3784,12 @@ clutter_check_windowing_backend (const char *backend_type)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CLUTTER_WINDOWING_MIR
|
||||||
|
if (backend_type == I_(CLUTTER_WINDOWING_MIR) &&
|
||||||
|
CLUTTER_IS_BACKEND_MIR (context->backend))
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
#ifdef CLUTTER_WINDOWING_GDK
|
#ifdef CLUTTER_WINDOWING_GDK
|
||||||
if (backend_type == I_(CLUTTER_WINDOWING_GDK) &&
|
if (backend_type == I_(CLUTTER_WINDOWING_GDK) &&
|
||||||
CLUTTER_IS_BACKEND_GDK (context->backend))
|
CLUTTER_IS_BACKEND_GDK (context->backend))
|
||||||
|
46
clutter/mir/clutter-backend-mir-priv.h
Normal file
46
clutter/mir/clutter-backend-mir-priv.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_BACKEND_MIR_PRIV_H__
|
||||||
|
#define __CLUTTER_BACKEND_MIR_PRIV_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-backend.h>
|
||||||
|
#include <mir_toolkit/mir_client_library.h>
|
||||||
|
|
||||||
|
#include "clutter-backend-private.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
struct _ClutterBackendMir
|
||||||
|
{
|
||||||
|
ClutterBackend parent_instance;
|
||||||
|
|
||||||
|
MirConnection *mir_connection;
|
||||||
|
GSource *mir_source;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_BACKEND_MIR_PRIV_H__ */
|
231
clutter/mir/clutter-backend-mir.c
Normal file
231
clutter/mir/clutter-backend-mir.c
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-debug.h"
|
||||||
|
#include "clutter-main.h"
|
||||||
|
#include "clutter-stage-private.h"
|
||||||
|
|
||||||
|
#include "mir/clutter-backend-mir-priv.h"
|
||||||
|
#include "mir/clutter-backend-mir.h"
|
||||||
|
#include "mir/clutter-device-manager-mir.h"
|
||||||
|
#include "mir/clutter-event-mir.h"
|
||||||
|
#include "mir/clutter-stage-mir.h"
|
||||||
|
#include "mir/clutter-mir.h"
|
||||||
|
|
||||||
|
#define clutter_backend_mir_get_type _clutter_backend_mir_get_type
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterBackendMir, clutter_backend_mir, CLUTTER_TYPE_BACKEND);
|
||||||
|
|
||||||
|
static MirConnection *_foreign_connection = NULL;
|
||||||
|
static gboolean _no_event_dispatch = FALSE;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_backend_mir_post_parse (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
||||||
|
|
||||||
|
backend_mir->mir_connection = _foreign_connection;
|
||||||
|
if (backend_mir->mir_connection == NULL)
|
||||||
|
backend_mir->mir_connection = mir_connect_sync (NULL, "Clutter");
|
||||||
|
|
||||||
|
if (!mir_connection_is_valid (backend_mir->mir_connection))
|
||||||
|
{
|
||||||
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
|
"Failed to open Mir display socket %s",
|
||||||
|
mir_connection_get_error_message (backend_mir->mir_connection));
|
||||||
|
mir_connection_release (backend_mir->mir_connection);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set (clutter_settings_get_default (), "font-dpi", 96 * 1024, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglRenderer *
|
||||||
|
clutter_backend_mir_get_renderer (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
||||||
|
CoglRenderer *renderer;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Creating a new Mir renderer");
|
||||||
|
|
||||||
|
renderer = cogl_renderer_new ();
|
||||||
|
|
||||||
|
cogl_renderer_set_winsys_id (renderer, COGL_WINSYS_ID_EGL_MIR);
|
||||||
|
cogl_mir_renderer_set_foreign_connection (renderer,
|
||||||
|
backend_mir->mir_connection);
|
||||||
|
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglDisplay *
|
||||||
|
clutter_backend_mir_get_display (ClutterBackend *backend,
|
||||||
|
CoglRenderer *renderer,
|
||||||
|
CoglSwapChain *swap_chain,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
CoglOnscreenTemplate *onscreen_template = NULL;
|
||||||
|
CoglDisplay *display;
|
||||||
|
|
||||||
|
onscreen_template = cogl_onscreen_template_new (swap_chain);
|
||||||
|
|
||||||
|
if (!cogl_renderer_check_onscreen_template (renderer,
|
||||||
|
onscreen_template,
|
||||||
|
error))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
display = cogl_display_new (renderer, onscreen_template);
|
||||||
|
|
||||||
|
return display;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (onscreen_template)
|
||||||
|
cogl_object_unref (onscreen_template);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_mir_event_cb (CoglMirEvent *mir_event,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend = data;
|
||||||
|
_clutter_mir_handle_event (backend, mir_event->surface, mir_event->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_events_mir_init (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
||||||
|
CoglRenderer *cogl_renderer = backend->cogl_renderer;
|
||||||
|
|
||||||
|
backend->device_manager = _clutter_device_manager_mir_new (backend);
|
||||||
|
|
||||||
|
if (_no_event_dispatch)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cogl_mir_renderer_add_event_listener (cogl_renderer, on_mir_event_cb, backend);
|
||||||
|
backend_mir->mir_source = _clutter_event_source_mir_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_mir_init (ClutterBackendMir *backend_mir)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_mir_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
||||||
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
||||||
|
CoglRenderer *cogl_renderer = backend->cogl_renderer;
|
||||||
|
|
||||||
|
g_clear_object (&backend->device_manager);
|
||||||
|
g_clear_pointer (&backend_mir->mir_source, g_source_unref);
|
||||||
|
cogl_mir_renderer_remove_event_listener (cogl_renderer, on_mir_event_cb,
|
||||||
|
backend);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_backend_mir_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_mir_class_init (ClutterBackendMirClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->dispose = clutter_backend_mir_dispose;
|
||||||
|
|
||||||
|
backend_class->stage_window_type = CLUTTER_TYPE_STAGE_MIR;
|
||||||
|
|
||||||
|
backend_class->post_parse = clutter_backend_mir_post_parse;
|
||||||
|
backend_class->get_renderer = clutter_backend_mir_get_renderer;
|
||||||
|
backend_class->get_display = clutter_backend_mir_get_display;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_mir_set_connection
|
||||||
|
* @connection: pointer to a mir 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_mir_set_connection() before g_option_context_parse().
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_mir_set_connection (MirConnection *connection)
|
||||||
|
{
|
||||||
|
g_return_if_fail (mir_connection_is_valid (connection));
|
||||||
|
|
||||||
|
if (_clutter_context_is_initialized ())
|
||||||
|
{
|
||||||
|
g_warning ("%s() can only be used before calling clutter_init()",
|
||||||
|
G_STRFUNC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_foreign_connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_mir_disable_event_retrieval:
|
||||||
|
*
|
||||||
|
* Disables the dispatch of the events in the main loop.
|
||||||
|
*
|
||||||
|
* This is useful for integrating Clutter with another library that will do the
|
||||||
|
* event dispatch;
|
||||||
|
*
|
||||||
|
* This function can only be called before calling clutter_init().
|
||||||
|
*
|
||||||
|
* This function should not be normally used by applications.
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_mir_disable_event_retrieval (void)
|
||||||
|
{
|
||||||
|
if (_clutter_context_is_initialized ())
|
||||||
|
{
|
||||||
|
g_warning ("%s() can only be used before calling clutter_init()",
|
||||||
|
G_STRFUNC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_no_event_dispatch = TRUE;
|
||||||
|
}
|
55
clutter/mir/clutter-backend-mir.h
Normal file
55
clutter/mir/clutter-backend-mir.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_BACKEND_MIR_H__
|
||||||
|
#define __CLUTTER_BACKEND_MIR_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-backend.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_BACKEND_MIR (_clutter_backend_mir_get_type ())
|
||||||
|
#define CLUTTER_BACKEND_MIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_MIR, ClutterBackendMir))
|
||||||
|
#define CLUTTER_IS_BACKEND_MIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_MIR))
|
||||||
|
#define CLUTTER_BACKEND_MIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_MIR, ClutterBackendMirClass))
|
||||||
|
#define CLUTTER_IS_BACKEND_MIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_MIR))
|
||||||
|
#define CLUTTER_BACKEND_MIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_MIR, ClutterBackendMirClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterBackendMir ClutterBackendMir;
|
||||||
|
typedef struct _ClutterBackendMirClass ClutterBackendMirClass;
|
||||||
|
|
||||||
|
struct _ClutterBackendMirClass
|
||||||
|
{
|
||||||
|
ClutterBackendClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType _clutter_backend_mir_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_events_mir_init (ClutterBackend *backend);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_BACKEND_MIR_H__ */
|
192
clutter/mir/clutter-device-manager-mir.c
Normal file
192
clutter/mir/clutter-device-manager-mir.c
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-device-manager-private.h"
|
||||||
|
#include "clutter-input-device-mir.h"
|
||||||
|
#include "clutter-device-manager-mir.h"
|
||||||
|
|
||||||
|
static guint device_counter;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterDeviceManagerMir, _clutter_device_manager_mir, CLUTTER_TYPE_DEVICE_MANAGER);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_device_manager_mir_add_device (ClutterDeviceManager *manager,
|
||||||
|
ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerMir *manager_mir = CLUTTER_DEVICE_MANAGER_MIR (manager);
|
||||||
|
manager_mir->devices = g_slist_prepend (manager_mir->devices, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_device_manager_mir_remove_device (ClutterDeviceManager *manager,
|
||||||
|
ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerMir *manager_mir = CLUTTER_DEVICE_MANAGER_MIR (manager);
|
||||||
|
manager_mir->devices = g_slist_remove (manager_mir->devices, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GSList *
|
||||||
|
clutter_device_manager_mir_get_devices (ClutterDeviceManager *manager)
|
||||||
|
{
|
||||||
|
return CLUTTER_DEVICE_MANAGER_MIR (manager)->devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterInputDevice *
|
||||||
|
clutter_device_manager_mir_get_core_device (ClutterDeviceManager *manager,
|
||||||
|
ClutterInputDeviceType type)
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerMir *manager_mir;
|
||||||
|
|
||||||
|
manager_mir = CLUTTER_DEVICE_MANAGER_MIR (manager);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case CLUTTER_POINTER_DEVICE:
|
||||||
|
return manager_mir->core_pointer;
|
||||||
|
|
||||||
|
case CLUTTER_KEYBOARD_DEVICE:
|
||||||
|
return manager_mir->core_keyboard;
|
||||||
|
|
||||||
|
case CLUTTER_EXTENSION_DEVICE:
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterInputDevice *
|
||||||
|
clutter_device_manager_mir_get_device (ClutterDeviceManager *manager,
|
||||||
|
gint id)
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerMir *manager_mir =
|
||||||
|
CLUTTER_DEVICE_MANAGER_MIR (manager);
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = manager_mir->devices; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *device = l->data;
|
||||||
|
|
||||||
|
if (clutter_input_device_get_device_id (device) == id)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_device_manager_mir_constructed (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend;
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterDeviceManagerMir *manager_mir;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
|
manager = CLUTTER_DEVICE_MANAGER (gobject);
|
||||||
|
manager_mir = CLUTTER_DEVICE_MANAGER_MIR (manager);
|
||||||
|
|
||||||
|
g_object_get (manager, "backend", &backend, NULL);
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_MIR,
|
||||||
|
"id", device_counter++,
|
||||||
|
"backend", backend,
|
||||||
|
"device-manager", manager,
|
||||||
|
"device-type", CLUTTER_POINTER_DEVICE,
|
||||||
|
"device-mode", CLUTTER_INPUT_MODE_MASTER,
|
||||||
|
"name", "Mir pointer",
|
||||||
|
"enabled", TRUE,
|
||||||
|
"has-cursor", TRUE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
manager_mir->core_pointer = device;
|
||||||
|
_clutter_device_manager_add_device (manager, CLUTTER_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_MIR,
|
||||||
|
"id", device_counter++,
|
||||||
|
"backend", backend,
|
||||||
|
"device-manager", manager,
|
||||||
|
"device-type", CLUTTER_KEYBOARD_DEVICE,
|
||||||
|
"device-mode", CLUTTER_INPUT_MODE_MASTER,
|
||||||
|
"name", "Mir keyboard",
|
||||||
|
"enabled", TRUE,
|
||||||
|
"has-cursor", FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
manager_mir->core_keyboard = device;
|
||||||
|
_clutter_device_manager_add_device (manager, CLUTTER_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
_clutter_input_device_set_associated_device (manager_mir->core_pointer,
|
||||||
|
manager_mir->core_keyboard);
|
||||||
|
_clutter_input_device_set_associated_device (manager_mir->core_keyboard,
|
||||||
|
manager_mir->core_pointer);
|
||||||
|
|
||||||
|
if (G_OBJECT_CLASS (_clutter_device_manager_mir_parent_class)->constructed)
|
||||||
|
G_OBJECT_CLASS (_clutter_device_manager_mir_parent_class)->constructed (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_device_manager_mir_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerMir *manager_mir;
|
||||||
|
|
||||||
|
manager_mir = CLUTTER_DEVICE_MANAGER_MIR (gobject);
|
||||||
|
g_slist_free_full (manager_mir->devices, g_object_unref);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (_clutter_device_manager_mir_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_device_manager_mir_class_init (ClutterDeviceManagerMirClass *klass)
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerClass *manager_class;
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
gobject_class->constructed = clutter_device_manager_mir_constructed;
|
||||||
|
gobject_class->finalize = clutter_device_manager_mir_finalize;
|
||||||
|
|
||||||
|
manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
|
||||||
|
manager_class->add_device = clutter_device_manager_mir_add_device;
|
||||||
|
manager_class->remove_device = clutter_device_manager_mir_remove_device;
|
||||||
|
manager_class->get_devices = clutter_device_manager_mir_get_devices;
|
||||||
|
manager_class->get_core_device = clutter_device_manager_mir_get_core_device;
|
||||||
|
manager_class->get_device = clutter_device_manager_mir_get_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clutter_device_manager_mir_init (ClutterDeviceManagerMir *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterDeviceManager *
|
||||||
|
_clutter_device_manager_mir_new (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
return g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_MIR,
|
||||||
|
"backend", backend,
|
||||||
|
NULL);
|
||||||
|
}
|
64
clutter/mir/clutter-device-manager-mir.h
Normal file
64
clutter/mir/clutter-device-manager-mir.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_DEVICE_MANAGER_MIR_H__
|
||||||
|
#define __CLUTTER_DEVICE_MANAGER_MIR_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter-device-manager.h>
|
||||||
|
#include <clutter/clutter-backend.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_DEVICE_MANAGER_MIR (_clutter_device_manager_mir_get_type ())
|
||||||
|
#define CLUTTER_DEVICE_MANAGER_MIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_MIR, ClutterDeviceManagerMir))
|
||||||
|
#define CLUTTER_IS_DEVICE_MANAGER_MIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_MIR))
|
||||||
|
#define CLUTTER_DEVICE_MANAGER_MIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_MIR, ClutterDeviceManagerMirClass))
|
||||||
|
#define CLUTTER_IS_DEVICE_MANAGER_MIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_MIR))
|
||||||
|
#define CLUTTER_DEVICE_MANAGER_MIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_MIR, ClutterDeviceManagerMirClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterDeviceManagerMir ClutterDeviceManagerMir;
|
||||||
|
typedef struct _ClutterDeviceManagerMirClass ClutterDeviceManagerMirClass;
|
||||||
|
|
||||||
|
struct _ClutterDeviceManagerMir
|
||||||
|
{
|
||||||
|
ClutterDeviceManager parent_instance;
|
||||||
|
|
||||||
|
GSList *devices;
|
||||||
|
ClutterInputDevice *core_pointer;
|
||||||
|
ClutterInputDevice *core_keyboard;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterDeviceManagerMirClass
|
||||||
|
{
|
||||||
|
ClutterDeviceManagerClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType _clutter_device_manager_mir_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
ClutterDeviceManager *
|
||||||
|
_clutter_device_manager_mir_new (ClutterBackend *backend);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_DEVICE_MANAGER_MIR_H__ */
|
395
clutter/mir/clutter-event-mir.c
Normal file
395
clutter/mir/clutter-event-mir.c
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-mir.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
#include "clutter-event-private.h"
|
||||||
|
#include "clutter-stage-mir.h"
|
||||||
|
#include "clutter-stage-private.h"
|
||||||
|
#include "clutter-backend-mir-priv.h"
|
||||||
|
#include "clutter-device-manager-private.h"
|
||||||
|
#include "evdev/clutter-xkb-utils.h"
|
||||||
|
|
||||||
|
#include "clutter-event-mir.h"
|
||||||
|
|
||||||
|
#define NANO_TO_MILLI(x) ((x) / 1000000)
|
||||||
|
|
||||||
|
/* Using the clutter threads lock would cause a dead-lock when resizing */
|
||||||
|
static GMutex mir_event_lock;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_event_source_mir_check (GSource *source)
|
||||||
|
{
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
g_mutex_lock (&mir_event_lock);
|
||||||
|
|
||||||
|
retval = clutter_events_pending ();
|
||||||
|
|
||||||
|
g_mutex_unlock (&mir_event_lock);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_event_source_mir_prepare (GSource *source, gint *timeout)
|
||||||
|
{
|
||||||
|
*timeout = -1;
|
||||||
|
return clutter_event_source_mir_check (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_event_source_mir_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterEvent *event;
|
||||||
|
|
||||||
|
g_mutex_lock (&mir_event_lock);
|
||||||
|
_clutter_threads_acquire_lock ();
|
||||||
|
|
||||||
|
event = clutter_event_get ();
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
{
|
||||||
|
/* forward the event into clutter for emission etc. */
|
||||||
|
_clutter_stage_queue_event (event->any.stage, event, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
_clutter_threads_release_lock ();
|
||||||
|
g_mutex_unlock (&mir_event_lock);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_event_source_mir_finalize (GSource *source)
|
||||||
|
{
|
||||||
|
g_mutex_clear (&mir_event_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs clutter_event_source_mir_funcs = {
|
||||||
|
clutter_event_source_mir_prepare,
|
||||||
|
clutter_event_source_mir_check,
|
||||||
|
clutter_event_source_mir_dispatch,
|
||||||
|
clutter_event_source_mir_finalize
|
||||||
|
};
|
||||||
|
|
||||||
|
GSource *
|
||||||
|
_clutter_event_source_mir_new (void)
|
||||||
|
{
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
source = g_source_new (&clutter_event_source_mir_funcs, sizeof (GSource));
|
||||||
|
|
||||||
|
g_mutex_init (&mir_event_lock);
|
||||||
|
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ClutterModifierType
|
||||||
|
translate_mir_modifier (unsigned int key_modifiers, MirMotionButton button_state)
|
||||||
|
{
|
||||||
|
ClutterModifierType clutter_modifiers = 0;
|
||||||
|
|
||||||
|
if (key_modifiers == mir_key_modifier_none && button_state == 0)
|
||||||
|
return clutter_modifiers;
|
||||||
|
|
||||||
|
if (key_modifiers & mir_key_modifier_alt)
|
||||||
|
clutter_modifiers |= CLUTTER_MOD1_MASK;
|
||||||
|
|
||||||
|
if (key_modifiers & mir_key_modifier_shift)
|
||||||
|
clutter_modifiers |= CLUTTER_SHIFT_MASK;
|
||||||
|
|
||||||
|
if (key_modifiers & mir_key_modifier_ctrl)
|
||||||
|
clutter_modifiers |= CLUTTER_CONTROL_MASK;
|
||||||
|
|
||||||
|
if (key_modifiers & mir_key_modifier_meta)
|
||||||
|
clutter_modifiers |= CLUTTER_META_MASK;
|
||||||
|
|
||||||
|
if (key_modifiers & mir_key_modifier_caps_lock)
|
||||||
|
clutter_modifiers |= CLUTTER_LOCK_MASK;
|
||||||
|
|
||||||
|
if (button_state & mir_motion_button_primary)
|
||||||
|
clutter_modifiers |= CLUTTER_BUTTON1_MASK;
|
||||||
|
|
||||||
|
if (button_state & mir_motion_button_secondary)
|
||||||
|
clutter_modifiers |= CLUTTER_BUTTON3_MASK;
|
||||||
|
|
||||||
|
if (button_state & mir_motion_button_tertiary)
|
||||||
|
clutter_modifiers |= CLUTTER_BUTTON2_MASK;
|
||||||
|
|
||||||
|
return clutter_modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gunichar
|
||||||
|
get_unicode_value (int32_t key_code)
|
||||||
|
{
|
||||||
|
gunichar unicode = '\0';
|
||||||
|
char text[8];
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = xkb_keysym_to_utf8 (key_code, text, sizeof (text));
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
unicode = g_utf8_get_char_validated (text, size);
|
||||||
|
|
||||||
|
if (unicode == -1 || unicode == -2)
|
||||||
|
unicode = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return unicode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_mir_handle_event (ClutterBackend *backend,
|
||||||
|
MirSurface *surface,
|
||||||
|
MirEvent *mir_event)
|
||||||
|
{
|
||||||
|
ClutterStageManager *stage_manager;
|
||||||
|
ClutterInputDevice *device = NULL;
|
||||||
|
ClutterStage *stage = NULL;
|
||||||
|
ClutterEvent *event = NULL;
|
||||||
|
ClutterModifierType modifiers;
|
||||||
|
MirMotionButton button_state;
|
||||||
|
MirMotionPointer *pointer;
|
||||||
|
const GSList *l;
|
||||||
|
|
||||||
|
stage_manager = clutter_stage_manager_get_default ();
|
||||||
|
|
||||||
|
for (l = clutter_stage_manager_peek_stages (stage_manager); l; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterStage* tmp_stage = l->data;
|
||||||
|
|
||||||
|
if (CLUTTER_IS_STAGE (tmp_stage) &&
|
||||||
|
clutter_mir_stage_get_mir_surface (tmp_stage) == surface)
|
||||||
|
{
|
||||||
|
stage = tmp_stage;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_mutex_lock (&mir_event_lock);
|
||||||
|
|
||||||
|
button_state = CLUTTER_STAGE_MIR (stage)->button_state;
|
||||||
|
|
||||||
|
switch (mir_event->type)
|
||||||
|
{
|
||||||
|
case mir_event_type_key:
|
||||||
|
if (mir_event->key.action == mir_key_action_multiple)
|
||||||
|
break;
|
||||||
|
|
||||||
|
device = clutter_device_manager_get_core_device (backend->device_manager,
|
||||||
|
CLUTTER_KEYBOARD_DEVICE);
|
||||||
|
|
||||||
|
event = clutter_event_new (mir_event->key.action == mir_key_action_down ?
|
||||||
|
CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
|
||||||
|
|
||||||
|
modifiers = translate_mir_modifier (mir_event->key.modifiers, button_state);
|
||||||
|
event->key.time = NANO_TO_MILLI (mir_event->key.event_time);
|
||||||
|
event->key.modifier_state = modifiers;
|
||||||
|
event->key.keyval = mir_event->key.key_code;
|
||||||
|
event->key.hardware_keycode = mir_event->key.scan_code + 8;
|
||||||
|
event->key.unicode_value = get_unicode_value (mir_event->key.key_code);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_event_type_motion:
|
||||||
|
pointer = mir_event->motion.pointer_coordinates;
|
||||||
|
device = clutter_device_manager_get_core_device (backend->device_manager,
|
||||||
|
CLUTTER_POINTER_DEVICE);
|
||||||
|
|
||||||
|
/* We need to send an ENTER event again if the stage is not focused anymore */
|
||||||
|
if (mir_event->motion.action != mir_motion_action_hover_enter &&
|
||||||
|
mir_event->motion.action != mir_motion_action_hover_exit &&
|
||||||
|
!_clutter_input_device_get_stage (device))
|
||||||
|
{
|
||||||
|
ClutterEvent *new_event = clutter_event_new (CLUTTER_ENTER);
|
||||||
|
modifiers = translate_mir_modifier (mir_event->motion.modifiers,
|
||||||
|
button_state);
|
||||||
|
|
||||||
|
clutter_event_set_time (new_event, NANO_TO_MILLI (mir_event->motion.event_time));
|
||||||
|
clutter_event_set_state (new_event, modifiers);
|
||||||
|
clutter_event_set_coords (new_event, pointer->x, pointer->y);
|
||||||
|
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
clutter_event_set_stage (new_event, stage);
|
||||||
|
clutter_event_set_device (new_event, device);
|
||||||
|
clutter_event_set_source_device (new_event, device);
|
||||||
|
|
||||||
|
_clutter_event_push (new_event, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mir_event->motion.action)
|
||||||
|
{
|
||||||
|
case mir_motion_action_down:
|
||||||
|
case mir_motion_action_pointer_down:
|
||||||
|
case mir_motion_action_up:
|
||||||
|
case mir_motion_action_pointer_up:
|
||||||
|
event = clutter_event_new ((mir_event->motion.action ==
|
||||||
|
mir_motion_action_down ||
|
||||||
|
mir_event->motion.action ==
|
||||||
|
mir_motion_action_pointer_down) ?
|
||||||
|
CLUTTER_BUTTON_PRESS :
|
||||||
|
CLUTTER_BUTTON_RELEASE);
|
||||||
|
|
||||||
|
event->button.button = 1;
|
||||||
|
event->button.click_count = 1;
|
||||||
|
|
||||||
|
button_state ^= mir_event->motion.button_state;
|
||||||
|
|
||||||
|
if (button_state == 0 || (button_state & mir_motion_button_primary))
|
||||||
|
event->button.button = 1;
|
||||||
|
else if (button_state & mir_motion_button_secondary)
|
||||||
|
event->button.button = 3;
|
||||||
|
else if (button_state & mir_motion_button_tertiary)
|
||||||
|
event->button.button = 2;
|
||||||
|
else if (button_state & mir_motion_button_back)
|
||||||
|
event->button.button = 8;
|
||||||
|
else if (button_state & mir_motion_button_forward)
|
||||||
|
event->button.button = 9;
|
||||||
|
|
||||||
|
button_state = mir_event->motion.button_state;
|
||||||
|
CLUTTER_STAGE_MIR (stage)->button_state = button_state;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case mir_motion_action_scroll:
|
||||||
|
event = clutter_event_new (CLUTTER_SCROLL);
|
||||||
|
if (ABS (pointer->hscroll) == 1 && pointer->vscroll == 0)
|
||||||
|
{
|
||||||
|
clutter_event_set_scroll_direction (event, pointer->hscroll < 0 ?
|
||||||
|
CLUTTER_SCROLL_LEFT :
|
||||||
|
CLUTTER_SCROLL_RIGHT);
|
||||||
|
}
|
||||||
|
else if (ABS (pointer->vscroll) == 1 && pointer->hscroll == 0)
|
||||||
|
{
|
||||||
|
clutter_event_set_scroll_direction (event, pointer->vscroll < 0 ?
|
||||||
|
CLUTTER_SCROLL_DOWN :
|
||||||
|
CLUTTER_SCROLL_UP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clutter_event_set_scroll_delta (event, -pointer->hscroll, -pointer->vscroll);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_motion_action_move:
|
||||||
|
case mir_motion_action_hover_move:
|
||||||
|
event = clutter_event_new (CLUTTER_MOTION);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_motion_action_hover_enter:
|
||||||
|
event = clutter_event_new (CLUTTER_ENTER);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_motion_action_hover_exit:
|
||||||
|
event = clutter_event_new (CLUTTER_LEAVE);
|
||||||
|
_clutter_input_device_set_stage (device, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
{
|
||||||
|
modifiers = translate_mir_modifier (mir_event->motion.modifiers,
|
||||||
|
button_state);
|
||||||
|
|
||||||
|
clutter_event_set_time (event, NANO_TO_MILLI (mir_event->motion.event_time));
|
||||||
|
clutter_event_set_state (event, modifiers);
|
||||||
|
clutter_event_set_coords (event, pointer->x, pointer->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_event_type_surface:
|
||||||
|
switch (mir_event->surface.attrib)
|
||||||
|
{
|
||||||
|
case mir_surface_attrib_state:
|
||||||
|
if (mir_event->surface.value == mir_surface_state_fullscreen)
|
||||||
|
{
|
||||||
|
_clutter_stage_update_state (stage,
|
||||||
|
0,
|
||||||
|
CLUTTER_STAGE_STATE_FULLSCREEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_clutter_stage_update_state (stage,
|
||||||
|
CLUTTER_STAGE_STATE_FULLSCREEN,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_surface_attrib_focus:
|
||||||
|
if (mir_event->surface.value == mir_surface_focused)
|
||||||
|
{
|
||||||
|
_clutter_stage_update_state (stage,
|
||||||
|
0,
|
||||||
|
CLUTTER_STAGE_STATE_ACTIVATED);
|
||||||
|
}
|
||||||
|
else /* if (mir_event->surface.value == mir_surface_unfocused) */
|
||||||
|
{
|
||||||
|
_clutter_stage_update_state (stage,
|
||||||
|
CLUTTER_STAGE_STATE_ACTIVATED,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mir_event_type_close_surface:
|
||||||
|
event = clutter_event_new (CLUTTER_DESTROY_NOTIFY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
{
|
||||||
|
clutter_event_set_stage (event, stage);
|
||||||
|
clutter_event_set_device (event, device);
|
||||||
|
clutter_event_set_source_device (event, device);
|
||||||
|
|
||||||
|
_clutter_event_push (event, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock (&mir_event_lock);
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
g_main_context_wakeup (NULL);
|
||||||
|
}
|
40
clutter/mir/clutter-event-mir.h
Normal file
40
clutter/mir/clutter-event-mir.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_EVENT_MIR_H__
|
||||||
|
#define __CLUTTER_EVENT_MIR_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-event.h>
|
||||||
|
|
||||||
|
#include <mir_toolkit/event.h>
|
||||||
|
|
||||||
|
GSource *
|
||||||
|
_clutter_event_source_mir_new (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_mir_handle_event (ClutterBackend *backend, MirSurface *surface, MirEvent *event);
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_EVENT_MIR_H__ */
|
55
clutter/mir/clutter-input-device-mir.c
Normal file
55
clutter/mir/clutter-input-device-mir.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-device-manager-private.h"
|
||||||
|
#include "clutter-input-device-mir.h"
|
||||||
|
|
||||||
|
typedef struct _ClutterInputDeviceClass ClutterInputDeviceMirClass;
|
||||||
|
|
||||||
|
#define clutter_input_device_mir_get_type _clutter_input_device_mir_get_type
|
||||||
|
G_DEFINE_TYPE (ClutterInputDeviceMir, clutter_input_device_mir, CLUTTER_TYPE_INPUT_DEVICE);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_input_device_mir_keycode_to_evdev (ClutterInputDevice *device,
|
||||||
|
guint hardware_keycode,
|
||||||
|
guint *evdev_keycode)
|
||||||
|
{
|
||||||
|
*evdev_keycode = hardware_keycode - 8;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_mir_class_init (ClutterInputDeviceMirClass *klass)
|
||||||
|
{
|
||||||
|
klass->keycode_to_evdev = clutter_input_device_mir_keycode_to_evdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_mir_init (ClutterInputDeviceMir *self)
|
||||||
|
{
|
||||||
|
}
|
45
clutter/mir/clutter-input-device-mir.h
Normal file
45
clutter/mir/clutter-input-device-mir.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_INPUT_DEVICE_MIR_H__
|
||||||
|
#define __CLUTTER_INPUT_DEVICE_MIR_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-event.h>
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_INPUT_DEVICE_MIR (_clutter_input_device_mir_get_type ())
|
||||||
|
#define CLUTTER_INPUT_DEVICE_MIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_MIR, ClutterInputDeviceMir))
|
||||||
|
#define CLUTTER_IS_INPUT_DEVICE_MIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_MIR))
|
||||||
|
|
||||||
|
typedef struct _ClutterInputDeviceMir ClutterInputDeviceMir;
|
||||||
|
|
||||||
|
struct _ClutterInputDeviceMir
|
||||||
|
{
|
||||||
|
ClutterInputDevice parent_device;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType _clutter_input_device_mir_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_INPUT_DEVICE_MIR_H__ */
|
57
clutter/mir/clutter-mir.h
Normal file
57
clutter/mir/clutter-mir.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:clutter-mir
|
||||||
|
* @short_description: Mir specific API
|
||||||
|
*
|
||||||
|
* The Mir backend for Clutter provides some specific API, allowing
|
||||||
|
* integration with the Mir client API for acessing the underlying data
|
||||||
|
* structures
|
||||||
|
*
|
||||||
|
* The Clutter Mir API is available since Clutter 1.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_MIR_H__
|
||||||
|
#define __CLUTTER_MIR_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <mir_toolkit/mir_client_library.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_1_22
|
||||||
|
MirSurface *clutter_mir_stage_get_mir_surface (ClutterStage *stage);
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_1_22
|
||||||
|
void clutter_mir_stage_set_mir_surface (ClutterStage *stage, MirSurface *surface);
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_1_22
|
||||||
|
void clutter_mir_set_connection (MirConnection *connection);
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_1_22
|
||||||
|
void clutter_mir_disable_event_retrieval (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __CLUTTER_MIR_H__ */
|
293
clutter/mir/clutter-stage-mir.c
Normal file
293
clutter/mir/clutter-stage-mir.c
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-mir.h"
|
||||||
|
#include "clutter-stage-mir.h"
|
||||||
|
#include "clutter-backend-mir-priv.h"
|
||||||
|
#include "clutter-stage-private.h"
|
||||||
|
#include "clutter-mir.h"
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#define clutter_stage_mir_get_type _clutter_stage_mir_get_type
|
||||||
|
|
||||||
|
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
|
||||||
|
|
||||||
|
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
||||||
|
static void clutter_stage_mir_set_fullscreen (ClutterStageWindow *stage_window,
|
||||||
|
gboolean fullscreen);
|
||||||
|
static void clutter_stage_mir_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||||
|
gboolean cursor_visible);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (ClutterStageMir,
|
||||||
|
clutter_stage_mir,
|
||||||
|
CLUTTER_TYPE_STAGE_COGL,
|
||||||
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||||
|
clutter_stage_window_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_stage_resized (CoglOnscreen *onscreen,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
clutter_actor_set_size (CLUTTER_ACTOR (user_data), width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_stage_mir_realize (ClutterStageWindow *stage_window)
|
||||||
|
{
|
||||||
|
ClutterStageMir *stage_mir = CLUTTER_STAGE_MIR (stage_window);
|
||||||
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
MirSurface *mir_surface;
|
||||||
|
|
||||||
|
if (!clutter_stage_window_parent_iface->realize (stage_window))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
cogl_framebuffer_allocate (COGL_FRAMEBUFFER (stage_cogl->onscreen), NULL);
|
||||||
|
mir_surface = cogl_mir_onscreen_get_surface (stage_cogl->onscreen);
|
||||||
|
|
||||||
|
if (!mir_surface_is_valid (mir_surface))
|
||||||
|
{
|
||||||
|
g_warning ("Realized Mir surface not valid");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stage_mir->foreign_mir_surface)
|
||||||
|
{
|
||||||
|
cogl_onscreen_add_resize_callback (stage_cogl->onscreen, on_stage_resized,
|
||||||
|
stage_cogl->wrapper, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage_mir->surface_state == mir_surface_state_fullscreen)
|
||||||
|
{
|
||||||
|
clutter_stage_mir_set_fullscreen (stage_window, TRUE);
|
||||||
|
stage_mir->surface_state = mir_surface_state_unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stage_mir->cursor_visible)
|
||||||
|
{
|
||||||
|
clutter_stage_mir_set_cursor_visible (stage_window, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_show (ClutterStageWindow *stage_window,
|
||||||
|
gboolean do_raise)
|
||||||
|
{
|
||||||
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
|
||||||
|
cogl_onscreen_show (stage_cogl->onscreen);
|
||||||
|
clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_hide (ClutterStageWindow *stage_window)
|
||||||
|
{
|
||||||
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
|
||||||
|
cogl_onscreen_hide (stage_cogl->onscreen);
|
||||||
|
clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||||
|
gboolean cursor_visible)
|
||||||
|
{
|
||||||
|
ClutterStageMir *stage_mir = CLUTTER_STAGE_MIR (stage_window);
|
||||||
|
ClutterActor *actor = _clutter_stage_window_get_wrapper (stage_window);
|
||||||
|
MirSurface *surface = clutter_mir_stage_get_mir_surface ((ClutterStage *) actor);
|
||||||
|
MirCursorConfiguration *cursor_conf;
|
||||||
|
|
||||||
|
if (mir_surface_is_valid (surface))
|
||||||
|
{
|
||||||
|
cursor_conf = mir_cursor_configuration_from_name (cursor_visible ?
|
||||||
|
mir_default_cursor_name :
|
||||||
|
mir_disabled_cursor_name);
|
||||||
|
mir_surface_configure_cursor (surface, cursor_conf);
|
||||||
|
mir_cursor_configuration_destroy (cursor_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
stage_mir->cursor_visible = cursor_visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_set_fullscreen (ClutterStageWindow *stage_window,
|
||||||
|
gboolean fullscreen)
|
||||||
|
{
|
||||||
|
ClutterStageMir *stage_mir = CLUTTER_STAGE_MIR (stage_window);
|
||||||
|
ClutterActor *actor = _clutter_stage_window_get_wrapper (stage_window);
|
||||||
|
MirSurface *surface = clutter_mir_stage_get_mir_surface ((ClutterStage *) actor);
|
||||||
|
|
||||||
|
if (!mir_surface_is_valid (surface))
|
||||||
|
{
|
||||||
|
stage_mir->surface_state = fullscreen ?
|
||||||
|
mir_surface_state_fullscreen :
|
||||||
|
mir_surface_state_unknown;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fullscreen)
|
||||||
|
{
|
||||||
|
stage_mir->surface_state = mir_surface_get_state (surface);
|
||||||
|
|
||||||
|
if (stage_mir->surface_state != mir_surface_state_fullscreen)
|
||||||
|
mir_wait_for (mir_surface_set_state (surface,
|
||||||
|
mir_surface_state_fullscreen));
|
||||||
|
}
|
||||||
|
else if (mir_surface_get_state (surface) == mir_surface_state_fullscreen)
|
||||||
|
{
|
||||||
|
mir_wait_for (mir_surface_set_state (surface, stage_mir->surface_state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_resize (ClutterStageWindow *stage_window,
|
||||||
|
gint width,
|
||||||
|
gint height)
|
||||||
|
{
|
||||||
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
|
||||||
|
if (stage_cogl->onscreen)
|
||||||
|
{
|
||||||
|
cogl_mir_onscreen_resize (stage_cogl->onscreen, width, height);
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_stage_mir_can_clip_redraws (ClutterStageWindow *stage_window)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_init (ClutterStageMir *stage_mir)
|
||||||
|
{
|
||||||
|
stage_mir->cursor_visible = TRUE;
|
||||||
|
stage_mir->surface_state = mir_surface_state_unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
||||||
|
{
|
||||||
|
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
|
||||||
|
|
||||||
|
iface->realize = clutter_stage_mir_realize;
|
||||||
|
iface->show = clutter_stage_mir_show;
|
||||||
|
iface->hide = clutter_stage_mir_hide;
|
||||||
|
iface->set_fullscreen = clutter_stage_mir_set_fullscreen;
|
||||||
|
iface->set_cursor_visible = clutter_stage_mir_set_cursor_visible;
|
||||||
|
iface->resize = clutter_stage_mir_resize;
|
||||||
|
iface->can_clip_redraws = clutter_stage_mir_can_clip_redraws;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_mir_class_init (ClutterStageMirClass *klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_mir_stage_get_mir_surface: (skip)
|
||||||
|
* @stage: a #ClutterStage
|
||||||
|
*
|
||||||
|
* Access the underlying data structure representing the surface that is
|
||||||
|
* backing the #ClutterStage
|
||||||
|
*
|
||||||
|
* Note: this function can only be called when running on the Mir
|
||||||
|
* platform. Calling this function at any other time will return %NULL.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the Mir surface associated with @stage
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
MirSurface *
|
||||||
|
clutter_mir_stage_get_mir_surface (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
|
||||||
|
ClutterStageCogl *stage_cogl;
|
||||||
|
|
||||||
|
if (!CLUTTER_IS_STAGE_COGL (stage_window))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
|
||||||
|
if (!cogl_is_onscreen (stage_cogl->onscreen))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return cogl_mir_onscreen_get_surface (stage_cogl->onscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_mir_stage_set_mir_surface:
|
||||||
|
* @stage: a #ClutterStage
|
||||||
|
* @surface: A Mir surface to associate with the @stage.
|
||||||
|
*
|
||||||
|
* Allows you to explicitly provide an existing Mir surface to associate
|
||||||
|
* with @stage, preventing Cogl from allocating a surface and shell surface for
|
||||||
|
* the stage automatically.
|
||||||
|
*
|
||||||
|
* This function must be called before @stage is shown.
|
||||||
|
*
|
||||||
|
* Note: this function can only be called when running on the Mir
|
||||||
|
* platform. Calling this function at any other time has no effect.
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_mir_stage_set_mir_surface (ClutterStage *stage,
|
||||||
|
MirSurface *surface)
|
||||||
|
{
|
||||||
|
ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
|
||||||
|
ClutterStageCogl *stage_cogl;
|
||||||
|
|
||||||
|
if (!CLUTTER_IS_STAGE_MIR (stage_window))
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_return_if_fail (mir_surface_is_valid (surface));
|
||||||
|
|
||||||
|
stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
|
||||||
|
if (stage_cogl->onscreen == NULL)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend = clutter_get_default_backend ();
|
||||||
|
|
||||||
|
/* Use the same default dimensions as clutter_stage_cogl_realize() */
|
||||||
|
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
|
||||||
|
800, 600);
|
||||||
|
|
||||||
|
cogl_mir_onscreen_set_foreign_surface (stage_cogl->onscreen, surface);
|
||||||
|
CLUTTER_STAGE_MIR (stage_window)->foreign_mir_surface = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_warning (G_STRLOC ": cannot set foreign surface for stage");
|
||||||
|
}
|
64
clutter/mir/clutter-stage-mir.h
Normal file
64
clutter/mir/clutter-stage-mir.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
|
||||||
|
* Authors:
|
||||||
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_STAGE_MIR_H__
|
||||||
|
#define __CLUTTER_STAGE_MIR_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-stage.h>
|
||||||
|
#include "cogl/clutter-stage-cogl.h"
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_STAGE_MIR (_clutter_stage_mir_get_type ())
|
||||||
|
#define CLUTTER_STAGE_MIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_MIR, ClutterStageMir))
|
||||||
|
#define CLUTTER_IS_STAGE_MIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_MIR))
|
||||||
|
#define CLUTTER_STAGE_MIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_MIR, ClutterStageMirClass))
|
||||||
|
#define CLUTTER_IS_STAGE_MIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_MIR))
|
||||||
|
#define CLUTTER_STAGE_MIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_MIR, ClutterStageMirClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterStageMir ClutterStageMir;
|
||||||
|
typedef struct _ClutterStageMirClass ClutterStageMirClass;
|
||||||
|
|
||||||
|
struct _ClutterStageMir
|
||||||
|
{
|
||||||
|
ClutterStageCogl parent_instance;
|
||||||
|
|
||||||
|
MirSurfaceState surface_state;
|
||||||
|
MirMotionButton button_state;
|
||||||
|
|
||||||
|
gboolean foreign_mir_surface;
|
||||||
|
gboolean cursor_visible;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterStageMirClass
|
||||||
|
{
|
||||||
|
ClutterStageCoglClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType _clutter_stage_mir_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_STAGE_MIR_H__ */
|
48
configure.ac
48
configure.ac
@ -274,6 +274,10 @@ AC_ARG_ENABLE([egl-backend],
|
|||||||
[AS_HELP_STRING([--enable-egl-backend=@<:@yes/no@:>@], [Enable the EGL framebuffer backend (default=no)])],
|
[AS_HELP_STRING([--enable-egl-backend=@<:@yes/no@:>@], [Enable the EGL framebuffer backend (default=no)])],
|
||||||
[enable_egl=$enableval],
|
[enable_egl=$enableval],
|
||||||
[enable_egl=no])
|
[enable_egl=no])
|
||||||
|
AC_ARG_ENABLE([mir-backend],
|
||||||
|
[AS_HELP_STRING([--enable-mir-backend=@<:@yes/no@:>@], [Enable the Mir client backend (default=no)])],
|
||||||
|
[enable_mir=$enableval],
|
||||||
|
[enable_mir=no])
|
||||||
AC_ARG_ENABLE([cex100-backend],
|
AC_ARG_ENABLE([cex100-backend],
|
||||||
[AS_HELP_STRING([--enable-cex100-backend=@<:@yes/no@:>@], [Enable the CEx100 backend (default=no)])],
|
[AS_HELP_STRING([--enable-cex100-backend=@<:@yes/no@:>@], [Enable the CEx100 backend (default=no)])],
|
||||||
[enable_cex100=$enableval],
|
[enable_cex100=$enableval],
|
||||||
@ -465,6 +469,45 @@ AS_IF([test "x$enable_win32" = "xyes"],
|
|||||||
SUPPORT_WIN32=1
|
SUPPORT_WIN32=1
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_mir" = "xyes"],
|
||||||
|
[
|
||||||
|
CLUTTER_BACKENDS="$CLUTTER_BACKENDS mir"
|
||||||
|
CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS mir"
|
||||||
|
|
||||||
|
SUPPORT_MIR=1
|
||||||
|
SUPPORT_COGL=1
|
||||||
|
|
||||||
|
have_cogl_mir=no
|
||||||
|
SAVED_CFLAGS="${CFLAGS}"
|
||||||
|
CFLAGS="`$PKG_CONFIG --cflags $CLUTTER_BASE_PC_FILES`"
|
||||||
|
|
||||||
|
# Manually check whether cogl has Mir support, as we can't rely on
|
||||||
|
# versioning yet.
|
||||||
|
AC_MSG_CHECKING([for Mir Cogl backend])
|
||||||
|
AC_TRY_COMPILE([#include <cogl/cogl.h>],
|
||||||
|
[
|
||||||
|
#ifndef COGL_HAS_EGL_PLATFORM_MIR_SUPPORT
|
||||||
|
#error "No Mir support in Cogl"
|
||||||
|
#endif
|
||||||
|
int main (void) { return 0; }
|
||||||
|
],
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
have_cogl_mir=yes,
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
have_cogl_mir=no)
|
||||||
|
|
||||||
|
CFLAGS="${SAVED_CFLAGS}"
|
||||||
|
|
||||||
|
AS_IF([test "x$have_cogl_mir" = "xno"],
|
||||||
|
[AC_MSG_ERROR([COGL_HAS_EGL_PLATFORM_MIR_SUPPORT not defined but the Mir backend has been explicitly enabled])])
|
||||||
|
|
||||||
|
PKG_CHECK_EXISTS([mirclient],
|
||||||
|
[BACKEND_PC_FILES="$BACKEND_PC_FILES mirclient"],
|
||||||
|
[])
|
||||||
|
|
||||||
|
AC_DEFINE([HAVE_CLUTTER_MIR], [1], [Have the mir client backend])
|
||||||
|
])
|
||||||
|
|
||||||
AS_IF([test "x$CLUTTER_BACKENDS" = "x"],
|
AS_IF([test "x$CLUTTER_BACKENDS" = "x"],
|
||||||
[
|
[
|
||||||
AC_MSG_ERROR([No backend enabled. You need to enable at least one backend.])
|
AC_MSG_ERROR([No backend enabled. You need to enable at least one backend.])
|
||||||
@ -519,6 +562,7 @@ AM_CONDITIONAL(SUPPORT_OSX, [test "x$SUPPORT_OSX" = "x1"])
|
|||||||
AM_CONDITIONAL(SUPPORT_WIN32, [test "x$SUPPORT_WIN32" = "x1"])
|
AM_CONDITIONAL(SUPPORT_WIN32, [test "x$SUPPORT_WIN32" = "x1"])
|
||||||
AM_CONDITIONAL(SUPPORT_CEX100, [test "x$SUPPORT_CEX100" = "x1"])
|
AM_CONDITIONAL(SUPPORT_CEX100, [test "x$SUPPORT_CEX100" = "x1"])
|
||||||
AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$SUPPORT_WAYLAND" = "x1"])
|
AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$SUPPORT_WAYLAND" = "x1"])
|
||||||
|
AM_CONDITIONAL(SUPPORT_MIR, [test "x$SUPPORT_MIR" = "x1"])
|
||||||
|
|
||||||
AM_CONDITIONAL(USE_COGL, [test "x$SUPPORT_COGL" = "x1"])
|
AM_CONDITIONAL(USE_COGL, [test "x$SUPPORT_COGL" = "x1"])
|
||||||
AM_CONDITIONAL(USE_TSLIB, [test "x$have_tslib" = "xyes"])
|
AM_CONDITIONAL(USE_TSLIB, [test "x$have_tslib" = "xyes"])
|
||||||
@ -563,6 +607,10 @@ AS_IF([test "x$SUPPORT_EGL" = "x1"],
|
|||||||
AS_IF([test "x$SUPPORT_WAYLAND" = "x1"],
|
AS_IF([test "x$SUPPORT_WAYLAND" = "x1"],
|
||||||
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
|
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
|
||||||
#define CLUTTER_WINDOWING_WAYLAND \"wayland\""])
|
#define CLUTTER_WINDOWING_WAYLAND \"wayland\""])
|
||||||
|
AS_IF([test "x$SUPPORT_MIR" = "x1"],
|
||||||
|
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
|
||||||
|
#define CLUTTER_WINDOWING_MIR \"mir\"
|
||||||
|
#define CLUTTER_INPUT_MIR \"mir\""])
|
||||||
AS_IF([test "x$SUPPORT_OSX" = "x1"],
|
AS_IF([test "x$SUPPORT_OSX" = "x1"],
|
||||||
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
|
[CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
|
||||||
#define CLUTTER_WINDOWING_OSX \"osx\"
|
#define CLUTTER_WINDOWING_OSX \"osx\"
|
||||||
|
Loading…
Reference in New Issue
Block a user