2016-05-04 08:19:23 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 Red Hat
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* Written by:
|
|
|
|
* Jonas Ådahl <jadahl@gmail.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib-object.h>
|
|
|
|
|
2016-05-09 01:59:54 +00:00
|
|
|
#include "backends/meta-backend-private.h"
|
|
|
|
#include "backends/meta-renderer.h"
|
Explicitly create the clutter context and backend
This changes the setup phase of clutter to not be result of calling an
init function that sets up a few global singletons, via global singleton
setup vfuncs.
The way it worked was that mutter first did some initial setup
(connecting to the X11 server), then set a "custom backend" setup vfunc
global, before calling clutter_init().
During the clutter_init() call, the context and backend was setup by
calling the global singleton getters, which implicitly created the
backend and context on-demand.
This has now changed to mutter explicitly creating a `ClutterContext`
(which is actually a `ClutterMainContext`, but with the name shortened to
be consistent with `CoglContext` and `MetaContext`), calling it with a
backend constructor vfunc and user data pointer.
This function now explicitly creates the backend, without having to go
via the previously set global vfunc.
This changes the behavior of some "get_default()" like functions, which
will now fail if called after mutter has shut down, as when it does so,
it now destroys the backends and contexts, not only its own, but the
clutter ones too.
The "ownership" of the clutter backend is also moved to
`ClutterContext`, and MetaBackend is changed to fetch it via the clutter
context.
This also removed the unused option parsing that existed in clutter.
In some places, NULL checks for fetching the clutter context, or
backend, and fetching the cogl context from the clutter backend, had to
be added.
The reason for this is that some code that handles EGL contexts attempts
to restore the cogl EGL context tracking so that the right EGL context
is used by cogl the next time. This makes no sense to do before Cogl and
Clutter are even initialized, which was the case. It wasn't noticed
because the relevant singletons were initialized on demand via their
"getters".
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2002>
2021-09-16 09:38:49 +00:00
|
|
|
#include "backends/x11/meta-backend-x11.h"
|
2016-05-04 08:19:23 +00:00
|
|
|
#include "backends/x11/meta-clutter-backend-x11.h"
|
2019-03-22 12:53:00 +00:00
|
|
|
#include "backends/x11/meta-keymap-x11.h"
|
2019-09-24 09:24:48 +00:00
|
|
|
#include "backends/x11/meta-seat-x11.h"
|
2019-03-22 12:53:00 +00:00
|
|
|
#include "backends/x11/meta-xkb-a11y-x11.h"
|
2019-03-29 20:18:07 +00:00
|
|
|
#include "backends/x11/nested/meta-stage-x11-nested.h"
|
2016-05-20 07:58:10 +00:00
|
|
|
#include "clutter/clutter-mutter.h"
|
2018-07-10 08:36:24 +00:00
|
|
|
#include "clutter/clutter.h"
|
2021-05-10 21:40:49 +00:00
|
|
|
#include "cogl/cogl-xlib.h"
|
2017-10-12 13:10:04 +00:00
|
|
|
#include "core/bell.h"
|
2018-07-10 08:36:24 +00:00
|
|
|
#include "meta/meta-backend.h"
|
2016-05-04 08:19:23 +00:00
|
|
|
|
2021-05-10 21:40:49 +00:00
|
|
|
typedef struct _MetaX11EventFilter MetaX11EventFilter;
|
|
|
|
|
|
|
|
struct _MetaX11EventFilter
|
2016-05-04 08:19:23 +00:00
|
|
|
{
|
2021-05-10 21:40:49 +00:00
|
|
|
MetaX11FilterFunc func;
|
|
|
|
gpointer data;
|
2016-05-04 08:19:23 +00:00
|
|
|
};
|
|
|
|
|
2021-09-16 09:33:21 +00:00
|
|
|
typedef struct _MetaClutterBackendX11Private
|
|
|
|
{
|
|
|
|
MetaBackend *backend;
|
|
|
|
} MetaClutterBackendX11Private;
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-16 09:33:21 +00:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaClutterBackendX11, meta_clutter_backend_x11,
|
|
|
|
CLUTTER_TYPE_BACKEND)
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
/* atoms; remember to add the code that assigns the atom value to
|
|
|
|
* the member of the MetaClutterBackendX11 structure if you add an
|
|
|
|
* atom name here. do not change the order!
|
|
|
|
*/
|
|
|
|
static const gchar *atom_names[] = {
|
|
|
|
"_NET_WM_PID",
|
|
|
|
"_NET_WM_PING",
|
|
|
|
"_NET_WM_STATE",
|
|
|
|
"_NET_WM_USER_TIME",
|
|
|
|
"WM_PROTOCOLS",
|
|
|
|
"WM_DELETE_WINDOW",
|
|
|
|
"_XEMBED",
|
|
|
|
"_XEMBED_INFO",
|
|
|
|
"_NET_WM_NAME",
|
|
|
|
"UTF8_STRING",
|
|
|
|
};
|
|
|
|
|
|
|
|
#define N_ATOM_NAMES G_N_ELEMENTS (atom_names)
|
|
|
|
|
|
|
|
/* various flags corresponding to pre init setup calls */
|
|
|
|
static gboolean clutter_enable_stereo = FALSE;
|
|
|
|
|
|
|
|
/* options */
|
|
|
|
static gboolean clutter_synchronise = FALSE;
|
|
|
|
|
|
|
|
/* X error trap */
|
|
|
|
static int TrappedErrorCode = 0;
|
|
|
|
static int (* old_error_handler) (Display *, XErrorEvent *);
|
|
|
|
|
|
|
|
static MetaX11FilterReturn
|
|
|
|
cogl_xlib_filter (XEvent *xevent,
|
|
|
|
ClutterEvent *event,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2021-09-15 09:58:16 +00:00
|
|
|
ClutterBackend *clutter_backend = data;
|
2021-05-10 21:40:49 +00:00
|
|
|
MetaX11FilterReturn retval;
|
|
|
|
CoglFilterReturn ret;
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
ret = cogl_xlib_renderer_handle_event (clutter_backend->cogl_renderer,
|
|
|
|
xevent);
|
2021-05-10 21:40:49 +00:00
|
|
|
switch (ret)
|
|
|
|
{
|
|
|
|
case COGL_FILTER_REMOVE:
|
|
|
|
retval = META_X11_FILTER_REMOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_FILTER_CONTINUE:
|
|
|
|
default:
|
|
|
|
retval = META_X11_FILTER_CONTINUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2021-09-15 09:58:16 +00:00
|
|
|
meta_clutter_backend_x11_finish_init (ClutterBackend *clutter_backend,
|
2021-09-14 14:51:57 +00:00
|
|
|
GError **error)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
2021-09-15 09:58:16 +00:00
|
|
|
MetaClutterBackendX11 *clutter_backend_x11 =
|
|
|
|
META_CLUTTER_BACKEND_X11 (clutter_backend);
|
Explicitly create the clutter context and backend
This changes the setup phase of clutter to not be result of calling an
init function that sets up a few global singletons, via global singleton
setup vfuncs.
The way it worked was that mutter first did some initial setup
(connecting to the X11 server), then set a "custom backend" setup vfunc
global, before calling clutter_init().
During the clutter_init() call, the context and backend was setup by
calling the global singleton getters, which implicitly created the
backend and context on-demand.
This has now changed to mutter explicitly creating a `ClutterContext`
(which is actually a `ClutterMainContext`, but with the name shortened to
be consistent with `CoglContext` and `MetaContext`), calling it with a
backend constructor vfunc and user data pointer.
This function now explicitly creates the backend, without having to go
via the previously set global vfunc.
This changes the behavior of some "get_default()" like functions, which
will now fail if called after mutter has shut down, as when it does so,
it now destroys the backends and contexts, not only its own, but the
clutter ones too.
The "ownership" of the clutter backend is also moved to
`ClutterContext`, and MetaBackend is changed to fetch it via the clutter
context.
This also removed the unused option parsing that existed in clutter.
In some places, NULL checks for fetching the clutter context, or
backend, and fetching the cogl context from the clutter backend, had to
be added.
The reason for this is that some code that handles EGL contexts attempts
to restore the cogl EGL context tracking so that the right EGL context
is used by cogl the next time. This makes no sense to do before Cogl and
Clutter are even initialized, which was the case. It wasn't noticed
because the relevant singletons were initialized on demand via their
"getters".
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2002>
2021-09-16 09:38:49 +00:00
|
|
|
MetaClutterBackendX11Private *priv =
|
|
|
|
meta_clutter_backend_x11_get_instance_private (clutter_backend_x11);
|
|
|
|
MetaBackendX11 *backend_x11 = META_BACKEND_X11 (priv->backend);
|
2021-05-10 21:40:49 +00:00
|
|
|
Atom atoms[N_ATOM_NAMES];
|
2021-09-15 10:13:26 +00:00
|
|
|
Screen *xscreen;
|
2021-05-10 21:40:49 +00:00
|
|
|
|
Explicitly create the clutter context and backend
This changes the setup phase of clutter to not be result of calling an
init function that sets up a few global singletons, via global singleton
setup vfuncs.
The way it worked was that mutter first did some initial setup
(connecting to the X11 server), then set a "custom backend" setup vfunc
global, before calling clutter_init().
During the clutter_init() call, the context and backend was setup by
calling the global singleton getters, which implicitly created the
backend and context on-demand.
This has now changed to mutter explicitly creating a `ClutterContext`
(which is actually a `ClutterMainContext`, but with the name shortened to
be consistent with `CoglContext` and `MetaContext`), calling it with a
backend constructor vfunc and user data pointer.
This function now explicitly creates the backend, without having to go
via the previously set global vfunc.
This changes the behavior of some "get_default()" like functions, which
will now fail if called after mutter has shut down, as when it does so,
it now destroys the backends and contexts, not only its own, but the
clutter ones too.
The "ownership" of the clutter backend is also moved to
`ClutterContext`, and MetaBackend is changed to fetch it via the clutter
context.
This also removed the unused option parsing that existed in clutter.
In some places, NULL checks for fetching the clutter context, or
backend, and fetching the cogl context from the clutter backend, had to
be added.
The reason for this is that some code that handles EGL contexts attempts
to restore the cogl EGL context tracking so that the right EGL context
is used by cogl the next time. This makes no sense to do before Cogl and
Clutter are even initialized, which was the case. It wasn't noticed
because the relevant singletons were initialized on demand via their
"getters".
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2002>
2021-09-16 09:38:49 +00:00
|
|
|
clutter_backend_x11->xdisplay = meta_backend_x11_get_xdisplay (backend_x11);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
/* add event filter for Cogl events */
|
2021-09-16 13:37:02 +00:00
|
|
|
meta_clutter_backend_x11_add_filter (clutter_backend_x11,
|
|
|
|
cogl_xlib_filter,
|
|
|
|
clutter_backend);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 10:13:26 +00:00
|
|
|
xscreen = DefaultScreenOfDisplay (clutter_backend_x11->xdisplay);
|
|
|
|
clutter_backend_x11->xscreen_num = XScreenNumberOfScreen (xscreen);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
clutter_backend_x11->xwin_root = RootWindow (clutter_backend_x11->xdisplay,
|
|
|
|
clutter_backend_x11->xscreen_num);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
if (clutter_synchronise)
|
2021-09-15 09:53:57 +00:00
|
|
|
XSynchronize (clutter_backend_x11->xdisplay, True);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
XInternAtoms (clutter_backend_x11->xdisplay,
|
2021-05-10 21:40:49 +00:00
|
|
|
(char **) atom_names, N_ATOM_NAMES,
|
|
|
|
False, atoms);
|
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
clutter_backend_x11->atom_NET_WM_PID = atoms[0];
|
|
|
|
clutter_backend_x11->atom_NET_WM_PING = atoms[1];
|
|
|
|
clutter_backend_x11->atom_NET_WM_STATE = atoms[2];
|
|
|
|
clutter_backend_x11->atom_NET_WM_USER_TIME = atoms[3];
|
|
|
|
clutter_backend_x11->atom_WM_PROTOCOLS = atoms[4];
|
|
|
|
clutter_backend_x11->atom_WM_DELETE_WINDOW = atoms[5];
|
|
|
|
clutter_backend_x11->atom_XEMBED = atoms[6];
|
|
|
|
clutter_backend_x11->atom_XEMBED_INFO = atoms[7];
|
|
|
|
clutter_backend_x11->atom_NET_WM_NAME = atoms[8];
|
|
|
|
clutter_backend_x11->atom_UTF8_STRING = atoms[9];
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
g_debug ("X Display '%s'[%p] opened (screen:%d, root:%u, dpi:%f)",
|
2021-09-14 14:35:36 +00:00
|
|
|
g_getenv ("DISPLAY"),
|
2021-09-15 09:53:57 +00:00
|
|
|
clutter_backend_x11->xdisplay,
|
|
|
|
clutter_backend_x11->xscreen_num,
|
|
|
|
(unsigned int) clutter_backend_x11->xwin_root,
|
2021-09-15 09:58:16 +00:00
|
|
|
clutter_backend_get_resolution (clutter_backend));
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_clutter_backend_x11_finalize (GObject *gobject)
|
|
|
|
{
|
2021-09-15 09:53:57 +00:00
|
|
|
MetaClutterBackendX11 *clutter_backend_x11 = META_CLUTTER_BACKEND_X11 (gobject);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-16 13:37:02 +00:00
|
|
|
meta_clutter_backend_x11_remove_filter (clutter_backend_x11,
|
|
|
|
cogl_xlib_filter,
|
|
|
|
clutter_backend_x11);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
XCloseDisplay (clutter_backend_x11->xdisplay);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_clutter_backend_x11_parent_class)->finalize (gobject);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-09-15 09:53:57 +00:00
|
|
|
update_last_event_time (MetaClutterBackendX11 *clutter_backend_x11,
|
2021-05-10 21:40:49 +00:00
|
|
|
XEvent *xevent)
|
|
|
|
{
|
|
|
|
Time current_time = CurrentTime;
|
2021-09-15 09:53:57 +00:00
|
|
|
Time last_time = clutter_backend_x11->last_event_time;
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
switch (xevent->type)
|
|
|
|
{
|
|
|
|
case KeyPress:
|
|
|
|
case KeyRelease:
|
|
|
|
current_time = xevent->xkey.time;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ButtonPress:
|
|
|
|
case ButtonRelease:
|
|
|
|
current_time = xevent->xbutton.time;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MotionNotify:
|
|
|
|
current_time = xevent->xmotion.time;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EnterNotify:
|
|
|
|
case LeaveNotify:
|
|
|
|
current_time = xevent->xcrossing.time;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PropertyNotify:
|
|
|
|
current_time = xevent->xproperty.time;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* only change the current event time if it's after the previous event
|
|
|
|
* time, or if it is at least 30 seconds earlier - in case the system
|
|
|
|
* clock was changed
|
|
|
|
*/
|
|
|
|
if ((current_time != CurrentTime) &&
|
|
|
|
(current_time > last_time || (last_time - current_time > (30 * 1000))))
|
2021-09-15 09:53:57 +00:00
|
|
|
clutter_backend_x11->last_event_time = current_time;
|
2021-05-10 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
check_onscreen_template (CoglRenderer *renderer,
|
|
|
|
CoglOnscreenTemplate *onscreen_template,
|
|
|
|
gboolean enable_stereo,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GError *internal_error = NULL;
|
|
|
|
|
|
|
|
cogl_onscreen_template_set_stereo_enabled (onscreen_template,
|
|
|
|
clutter_enable_stereo);
|
|
|
|
|
|
|
|
/* cogl_renderer_check_onscreen_template() is actually just a
|
|
|
|
* shorthand for creating a CoglDisplay, and calling
|
|
|
|
* cogl_display_setup() on it, then throwing the display away. If we
|
|
|
|
* could just return that display, then it would be more efficient
|
|
|
|
* not to use cogl_renderer_check_onscreen_template(). However, the
|
|
|
|
* backend API requires that we return an CoglDisplay that has not
|
|
|
|
* yet been setup, so one way or the other we'll have to discard the
|
|
|
|
* first display and make a new fresh one.
|
|
|
|
*/
|
|
|
|
if (cogl_renderer_check_onscreen_template (renderer, onscreen_template, &internal_error))
|
|
|
|
{
|
|
|
|
clutter_enable_stereo = enable_stereo;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Explicitly create the clutter context and backend
This changes the setup phase of clutter to not be result of calling an
init function that sets up a few global singletons, via global singleton
setup vfuncs.
The way it worked was that mutter first did some initial setup
(connecting to the X11 server), then set a "custom backend" setup vfunc
global, before calling clutter_init().
During the clutter_init() call, the context and backend was setup by
calling the global singleton getters, which implicitly created the
backend and context on-demand.
This has now changed to mutter explicitly creating a `ClutterContext`
(which is actually a `ClutterMainContext`, but with the name shortened to
be consistent with `CoglContext` and `MetaContext`), calling it with a
backend constructor vfunc and user data pointer.
This function now explicitly creates the backend, without having to go
via the previously set global vfunc.
This changes the behavior of some "get_default()" like functions, which
will now fail if called after mutter has shut down, as when it does so,
it now destroys the backends and contexts, not only its own, but the
clutter ones too.
The "ownership" of the clutter backend is also moved to
`ClutterContext`, and MetaBackend is changed to fetch it via the clutter
context.
This also removed the unused option parsing that existed in clutter.
In some places, NULL checks for fetching the clutter context, or
backend, and fetching the cogl context from the clutter backend, had to
be added.
The reason for this is that some code that handles EGL contexts attempts
to restore the cogl EGL context tracking so that the right EGL context
is used by cogl the next time. This makes no sense to do before Cogl and
Clutter are even initialized, which was the case. It wasn't noticed
because the relevant singletons were initialized on demand via their
"getters".
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2002>
2021-09-16 09:38:49 +00:00
|
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
2021-05-10 21:40:49 +00:00
|
|
|
internal_error != NULL
|
|
|
|
? internal_error->message
|
|
|
|
: "Creation of a CoglDisplay failed");
|
|
|
|
|
|
|
|
g_clear_error (&internal_error);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static CoglDisplay *
|
2021-09-15 09:58:16 +00:00
|
|
|
meta_clutter_backend_x11_get_display (ClutterBackend *clutter_backend,
|
2021-05-10 21:40:49 +00:00
|
|
|
CoglRenderer *renderer,
|
|
|
|
CoglSwapChain *swap_chain,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
CoglOnscreenTemplate *onscreen_template;
|
|
|
|
CoglDisplay *display = NULL;
|
|
|
|
gboolean res = FALSE;
|
|
|
|
|
|
|
|
onscreen_template = cogl_onscreen_template_new (swap_chain);
|
|
|
|
|
|
|
|
/* It's possible that the current renderer doesn't support transparency
|
|
|
|
* or doesn't support stereo, so we try the different combinations.
|
|
|
|
*/
|
|
|
|
if (clutter_enable_stereo)
|
|
|
|
res = check_onscreen_template (renderer, onscreen_template,
|
|
|
|
TRUE, error);
|
|
|
|
|
|
|
|
if (!res)
|
|
|
|
res = check_onscreen_template (renderer, onscreen_template,
|
|
|
|
FALSE, error);
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
display = cogl_display_new (renderer, onscreen_template);
|
|
|
|
|
|
|
|
cogl_object_unref (onscreen_template);
|
|
|
|
|
|
|
|
return display;
|
|
|
|
}
|
2016-05-04 08:19:23 +00:00
|
|
|
|
2016-05-09 01:59:54 +00:00
|
|
|
static CoglRenderer *
|
|
|
|
meta_clutter_backend_x11_get_renderer (ClutterBackend *clutter_backend,
|
|
|
|
GError **error)
|
|
|
|
{
|
2021-09-16 09:33:21 +00:00
|
|
|
MetaClutterBackendX11 *clutter_backend_x11 =
|
|
|
|
META_CLUTTER_BACKEND_X11 (clutter_backend);
|
|
|
|
MetaClutterBackendX11Private *priv =
|
|
|
|
meta_clutter_backend_x11_get_instance_private (clutter_backend_x11);
|
|
|
|
MetaRenderer *renderer = meta_backend_get_renderer (priv->backend);
|
2016-05-09 01:59:54 +00:00
|
|
|
|
|
|
|
return meta_renderer_create_cogl_renderer (renderer);
|
|
|
|
}
|
|
|
|
|
2016-05-20 07:58:10 +00:00
|
|
|
static ClutterStageWindow *
|
2021-09-15 09:58:16 +00:00
|
|
|
meta_clutter_backend_x11_create_stage (ClutterBackend *clutter_backend,
|
2016-05-20 07:58:10 +00:00
|
|
|
ClutterStage *wrapper,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ClutterStageWindow *stage;
|
|
|
|
GType stage_type;
|
|
|
|
|
|
|
|
if (meta_is_wayland_compositor ())
|
|
|
|
stage_type = META_TYPE_STAGE_X11_NESTED;
|
|
|
|
else
|
2019-03-22 12:53:00 +00:00
|
|
|
stage_type = META_TYPE_STAGE_X11;
|
2016-05-20 07:58:10 +00:00
|
|
|
|
|
|
|
stage = g_object_new (stage_type,
|
2021-09-15 09:58:16 +00:00
|
|
|
"backend", clutter_backend,
|
2016-05-20 07:58:10 +00:00
|
|
|
"wrapper", wrapper,
|
|
|
|
NULL);
|
|
|
|
return stage;
|
|
|
|
}
|
|
|
|
|
2021-05-10 21:40:49 +00:00
|
|
|
static gboolean
|
2021-09-15 09:53:57 +00:00
|
|
|
meta_clutter_backend_x11_process_event_filters (MetaClutterBackendX11 *clutter_backend_x11,
|
2021-05-10 21:40:49 +00:00
|
|
|
gpointer native,
|
|
|
|
ClutterEvent *event)
|
|
|
|
{
|
|
|
|
XEvent *xevent = native;
|
|
|
|
|
|
|
|
/* X11 filter functions have a higher priority */
|
2021-09-15 09:53:57 +00:00
|
|
|
if (clutter_backend_x11->event_filters != NULL)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
2021-09-15 09:53:57 +00:00
|
|
|
GSList *node = clutter_backend_x11->event_filters;
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
while (node != NULL)
|
|
|
|
{
|
|
|
|
MetaX11EventFilter *filter = node->data;
|
|
|
|
|
|
|
|
switch (filter->func (xevent, event, filter->data))
|
|
|
|
{
|
|
|
|
case META_X11_FILTER_CONTINUE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_X11_FILTER_TRANSLATE:
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case META_X11_FILTER_REMOVE:
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2019-03-22 12:53:00 +00:00
|
|
|
static gboolean
|
2021-03-11 20:51:39 +00:00
|
|
|
meta_clutter_backend_x11_translate_event (ClutterBackend *clutter_backend,
|
2019-03-22 12:53:00 +00:00
|
|
|
gpointer native,
|
|
|
|
ClutterEvent *event)
|
|
|
|
{
|
2021-09-15 09:53:57 +00:00
|
|
|
MetaClutterBackendX11 *clutter_backend_x11 =
|
2021-05-10 21:40:49 +00:00
|
|
|
META_CLUTTER_BACKEND_X11 (clutter_backend);
|
2021-09-16 09:33:21 +00:00
|
|
|
MetaClutterBackendX11Private *priv =
|
|
|
|
meta_clutter_backend_x11_get_instance_private (clutter_backend_x11);
|
2019-03-22 12:53:00 +00:00
|
|
|
MetaStageX11 *stage_x11;
|
2021-03-12 07:31:50 +00:00
|
|
|
ClutterSeat *seat;
|
2019-03-22 12:53:00 +00:00
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
if (meta_clutter_backend_x11_process_event_filters (clutter_backend_x11,
|
2021-05-10 21:40:49 +00:00
|
|
|
native,
|
|
|
|
event))
|
2019-03-22 12:53:00 +00:00
|
|
|
return TRUE;
|
|
|
|
|
2021-05-10 21:40:49 +00:00
|
|
|
/* we update the event time only for events that can
|
|
|
|
* actually reach Clutter's event queue
|
|
|
|
*/
|
2021-09-15 09:53:57 +00:00
|
|
|
update_last_event_time (clutter_backend_x11, native);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-03-11 20:51:39 +00:00
|
|
|
stage_x11 =
|
|
|
|
META_STAGE_X11 (clutter_backend_get_stage_window (clutter_backend));
|
2019-03-22 12:53:00 +00:00
|
|
|
if (meta_stage_x11_translate_event (stage_x11, native, event))
|
|
|
|
return TRUE;
|
|
|
|
|
2021-09-16 09:33:21 +00:00
|
|
|
seat = meta_backend_get_default_seat (priv->backend);
|
2021-03-12 07:31:50 +00:00
|
|
|
if (meta_seat_x11_translate_event (META_SEAT_X11 (seat), native, event))
|
2019-03-22 12:53:00 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2019-09-24 09:24:48 +00:00
|
|
|
static ClutterSeat *
|
2021-03-11 20:51:39 +00:00
|
|
|
meta_clutter_backend_x11_get_default_seat (ClutterBackend *clutter_backend)
|
2019-09-24 09:24:48 +00:00
|
|
|
{
|
2021-09-16 09:33:21 +00:00
|
|
|
MetaClutterBackendX11 *clutter_backend_x11 =
|
|
|
|
META_CLUTTER_BACKEND_X11 (clutter_backend);
|
|
|
|
MetaClutterBackendX11Private *priv =
|
|
|
|
meta_clutter_backend_x11_get_instance_private (clutter_backend_x11);
|
2019-03-22 12:53:00 +00:00
|
|
|
|
2021-09-16 09:33:21 +00:00
|
|
|
return meta_backend_get_default_seat (priv->backend);
|
2019-03-22 12:53:00 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 07:45:07 +00:00
|
|
|
static gboolean
|
2021-09-15 09:58:16 +00:00
|
|
|
meta_clutter_backend_x11_is_display_server (ClutterBackend *clutter_backend)
|
2020-07-09 07:45:07 +00:00
|
|
|
{
|
|
|
|
return meta_is_wayland_compositor ();
|
|
|
|
}
|
|
|
|
|
2016-05-04 08:19:23 +00:00
|
|
|
static void
|
|
|
|
meta_clutter_backend_x11_init (MetaClutterBackendX11 *clutter_backend_x11)
|
|
|
|
{
|
2021-05-10 21:40:49 +00:00
|
|
|
clutter_backend_x11->last_event_time = CurrentTime;
|
2016-05-04 08:19:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_clutter_backend_x11_class_init (MetaClutterBackendX11Class *klass)
|
|
|
|
{
|
2021-05-10 21:40:49 +00:00
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
2016-05-09 01:59:54 +00:00
|
|
|
ClutterBackendClass *clutter_backend_class = CLUTTER_BACKEND_CLASS (klass);
|
|
|
|
|
2021-05-10 21:40:49 +00:00
|
|
|
gobject_class->finalize = meta_clutter_backend_x11_finalize;
|
|
|
|
|
2021-09-14 14:51:57 +00:00
|
|
|
clutter_backend_class->finish_init = meta_clutter_backend_x11_finish_init;
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
clutter_backend_class->get_display = meta_clutter_backend_x11_get_display;
|
2016-05-09 01:59:54 +00:00
|
|
|
clutter_backend_class->get_renderer = meta_clutter_backend_x11_get_renderer;
|
2016-05-20 07:58:10 +00:00
|
|
|
clutter_backend_class->create_stage = meta_clutter_backend_x11_create_stage;
|
2019-03-22 12:53:00 +00:00
|
|
|
clutter_backend_class->translate_event = meta_clutter_backend_x11_translate_event;
|
2019-09-24 09:24:48 +00:00
|
|
|
clutter_backend_class->get_default_seat = meta_clutter_backend_x11_get_default_seat;
|
2020-07-09 07:45:07 +00:00
|
|
|
clutter_backend_class->is_display_server = meta_clutter_backend_x11_is_display_server;
|
2016-05-04 08:19:23 +00:00
|
|
|
}
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-16 09:33:21 +00:00
|
|
|
MetaClutterBackendX11 *
|
|
|
|
meta_clutter_backend_x11_new (MetaBackend *backend)
|
|
|
|
{
|
|
|
|
MetaClutterBackendX11 *clutter_backend_x11;
|
|
|
|
MetaClutterBackendX11Private *priv;
|
|
|
|
|
|
|
|
clutter_backend_x11 = g_object_new (META_TYPE_CLUTTER_BACKEND_X11, NULL);
|
|
|
|
priv = meta_clutter_backend_x11_get_instance_private (clutter_backend_x11);
|
|
|
|
priv->backend = backend;
|
|
|
|
|
|
|
|
return clutter_backend_x11;
|
|
|
|
}
|
|
|
|
|
2021-05-10 21:40:49 +00:00
|
|
|
static int
|
|
|
|
error_handler (Display *xdisplay,
|
|
|
|
XErrorEvent *error)
|
|
|
|
{
|
|
|
|
TrappedErrorCode = error->error_code;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_clutter_x11_trap_x_errors (void)
|
|
|
|
{
|
|
|
|
TrappedErrorCode = 0;
|
|
|
|
old_error_handler = XSetErrorHandler (error_handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
meta_clutter_x11_untrap_x_errors (void)
|
|
|
|
{
|
|
|
|
XSetErrorHandler (old_error_handler);
|
|
|
|
|
|
|
|
return TrappedErrorCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
Display *
|
|
|
|
meta_clutter_x11_get_default_display (void)
|
|
|
|
{
|
2021-09-15 09:58:16 +00:00
|
|
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
if (clutter_backend == NULL)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
g_critical ("The Clutter backend has not been initialised");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
if (!META_IS_CLUTTER_BACKEND_X11 (clutter_backend))
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
g_critical ("The Clutter backend is not a X11 backend");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
return META_CLUTTER_BACKEND_X11 (clutter_backend)->xdisplay;
|
2021-05-10 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
meta_clutter_x11_get_default_screen (void)
|
|
|
|
{
|
2021-09-15 09:58:16 +00:00
|
|
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
if (clutter_backend == NULL)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
g_critical ("The Clutter backend has not been initialised");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
if (!META_IS_CLUTTER_BACKEND_X11 (clutter_backend))
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
g_critical ("The Clutter backend is not a X11 backend");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
return META_CLUTTER_BACKEND_X11 (clutter_backend)->xscreen_num;
|
2021-05-10 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Window
|
|
|
|
meta_clutter_x11_get_root_window (void)
|
|
|
|
{
|
2021-09-15 09:58:16 +00:00
|
|
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
2021-05-10 21:40:49 +00:00
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
if (clutter_backend == NULL)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
g_critical ("The Clutter backend has not been initialised");
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
if (!META_IS_CLUTTER_BACKEND_X11 (clutter_backend))
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
g_critical ("The Clutter backend is not a X11 backend");
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2021-09-15 09:58:16 +00:00
|
|
|
return META_CLUTTER_BACKEND_X11 (clutter_backend)->xwin_root;
|
2021-05-10 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-09-16 13:37:02 +00:00
|
|
|
meta_clutter_backend_x11_add_filter (MetaClutterBackendX11 *clutter_backend_x11,
|
|
|
|
MetaX11FilterFunc func,
|
|
|
|
gpointer data)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
MetaX11EventFilter *filter;
|
|
|
|
|
|
|
|
g_return_if_fail (func != NULL);
|
|
|
|
|
|
|
|
filter = g_new0 (MetaX11EventFilter, 1);
|
|
|
|
filter->func = func;
|
|
|
|
filter->data = data;
|
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
clutter_backend_x11->event_filters =
|
|
|
|
g_slist_append (clutter_backend_x11->event_filters, filter);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-09-16 13:37:02 +00:00
|
|
|
meta_clutter_backend_x11_remove_filter (MetaClutterBackendX11 *clutter_backend_x11,
|
|
|
|
MetaX11FilterFunc func,
|
|
|
|
gpointer data)
|
2021-05-10 21:40:49 +00:00
|
|
|
{
|
|
|
|
GSList *tmp_list, *this;
|
|
|
|
MetaX11EventFilter *filter;
|
|
|
|
|
|
|
|
g_return_if_fail (func != NULL);
|
|
|
|
|
2021-09-15 09:53:57 +00:00
|
|
|
tmp_list = clutter_backend_x11->event_filters;
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
while (tmp_list)
|
|
|
|
{
|
|
|
|
filter = tmp_list->data;
|
|
|
|
this = tmp_list;
|
|
|
|
tmp_list = tmp_list->next;
|
|
|
|
|
|
|
|
if (filter->func == func && filter->data == data)
|
|
|
|
{
|
2021-09-15 09:53:57 +00:00
|
|
|
clutter_backend_x11->event_filters =
|
|
|
|
g_slist_remove_link (clutter_backend_x11->event_filters, this);
|
2021-05-10 21:40:49 +00:00
|
|
|
|
|
|
|
g_slist_free_1 (this);
|
|
|
|
g_free (filter);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_clutter_x11_set_use_stereo_stage (gboolean use_stereo)
|
|
|
|
{
|
|
|
|
if (_clutter_context_is_initialized ())
|
|
|
|
{
|
|
|
|
g_warning ("%s() can only be used before calling clutter_init()",
|
|
|
|
G_STRFUNC);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_debug ("STEREO stages are %s",
|
|
|
|
use_stereo ? "enabled" : "disabled");
|
|
|
|
|
|
|
|
clutter_enable_stereo = use_stereo;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_clutter_x11_get_use_stereo_stage (void)
|
|
|
|
{
|
|
|
|
return clutter_enable_stereo;
|
|
|
|
}
|