diff options
Diffstat (limited to 'clutter/mir/clutter-backend-mir.c')
-rw-r--r-- | clutter/mir/clutter-backend-mir.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/clutter/mir/clutter-backend-mir.c b/clutter/mir/clutter-backend-mir.c new file mode 100644 index 000000000..d537483da --- /dev/null +++ b/clutter/mir/clutter-backend-mir.c @@ -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; +} |