mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 12:32:05 +00:00
8613013ab0
Move Stage private API to a separate header.
364 lines
11 KiB
C
364 lines
11 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "clutter-stage-egl.h"
|
|
#include "clutter-egl.h"
|
|
#include "clutter-backend-egl.h"
|
|
|
|
#include "clutter-debug.h"
|
|
#include "clutter-event.h"
|
|
#include "clutter-enum-types.h"
|
|
#include "clutter-feature.h"
|
|
#include "clutter-main.h"
|
|
#include "clutter-private.h"
|
|
#include "clutter-stage-private.h"
|
|
#include "clutter-util.h"
|
|
|
|
#ifdef COGL_HAS_X11_SUPPORT
|
|
static ClutterStageWindowIface *clutter_stage_egl_parent_iface = NULL;
|
|
#endif
|
|
|
|
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
|
|
_clutter_stage_egl,
|
|
#ifdef COGL_HAS_X11_SUPPORT
|
|
CLUTTER_TYPE_STAGE_X11,
|
|
#else
|
|
G_TYPE_OBJECT,
|
|
#endif
|
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
|
clutter_stage_window_iface_init));
|
|
|
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
|
|
|
static void
|
|
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
|
|
{
|
|
ClutterBackend *backend = clutter_get_default_backend ();
|
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
|
|
|
CLUTTER_NOTE (BACKEND, "Unrealizing stage");
|
|
|
|
clutter_x11_trap_x_errors ();
|
|
|
|
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
|
|
{
|
|
XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
|
|
stage_x11->xwin = None;
|
|
}
|
|
else
|
|
stage_x11->xwin = None;
|
|
|
|
if (stage_egl->egl_surface != EGL_NO_SURFACE)
|
|
{
|
|
eglDestroySurface (clutter_eglx_display (), stage_egl->egl_surface);
|
|
stage_egl->egl_surface = EGL_NO_SURFACE;
|
|
}
|
|
|
|
XSync (backend_x11->xdpy, False);
|
|
|
|
clutter_x11_untrap_x_errors ();
|
|
}
|
|
|
|
static gboolean
|
|
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
|
ClutterBackend *backend;
|
|
ClutterBackendEGL *backend_egl;
|
|
ClutterBackendX11 *backend_x11;
|
|
EGLDisplay edpy;
|
|
|
|
CLUTTER_NOTE (BACKEND, "Realizing main stage");
|
|
|
|
backend = clutter_get_default_backend ();
|
|
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
|
|
|
edpy = clutter_eglx_display ();
|
|
|
|
if (stage_x11->xwin == None)
|
|
{
|
|
XSetWindowAttributes xattr;
|
|
unsigned long mask;
|
|
XVisualInfo *xvisinfo;
|
|
gfloat width, height;
|
|
|
|
CLUTTER_NOTE (MISC, "Creating stage X window");
|
|
|
|
xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
|
|
if (xvisinfo == NULL)
|
|
{
|
|
g_critical ("Unable to find suitable GL visual.");
|
|
return FALSE;
|
|
}
|
|
|
|
/* window attributes */
|
|
xattr.background_pixel = WhitePixel (backend_x11->xdpy,
|
|
backend_x11->xscreen_num);
|
|
xattr.border_pixel = 0;
|
|
xattr.colormap = XCreateColormap (backend_x11->xdpy,
|
|
backend_x11->xwin_root,
|
|
xvisinfo->visual,
|
|
AllocNone);
|
|
mask = CWBorderPixel | CWColormap;
|
|
|
|
/* Call get_size - this will either get the geometry size (which
|
|
* before we create the window is set to 640x480), or if a size
|
|
* is set, it will get that. This lets you set a size on the
|
|
* stage before it's realized.
|
|
*/
|
|
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper),
|
|
&width,
|
|
&height);
|
|
stage_x11->xwin_width = (gint)width;
|
|
stage_x11->xwin_height = (gint)height;
|
|
|
|
stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
|
|
backend_x11->xwin_root,
|
|
0, 0,
|
|
stage_x11->xwin_width,
|
|
stage_x11->xwin_height,
|
|
0,
|
|
xvisinfo->depth,
|
|
InputOutput,
|
|
xvisinfo->visual,
|
|
mask, &xattr);
|
|
|
|
CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
|
|
stage_window,
|
|
(unsigned int) stage_x11->xwin,
|
|
stage_x11->xwin_width,
|
|
stage_x11->xwin_height);
|
|
|
|
XFree (xvisinfo);
|
|
}
|
|
|
|
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
|
{
|
|
stage_egl->egl_surface =
|
|
eglCreateWindowSurface (edpy,
|
|
backend_egl->egl_config,
|
|
(NativeWindowType) stage_x11->xwin,
|
|
NULL);
|
|
}
|
|
|
|
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
|
g_warning ("Unable to create an EGL surface");
|
|
|
|
if (clutter_x11_has_event_retrieval ())
|
|
{
|
|
if (clutter_x11_has_xinput ())
|
|
{
|
|
XSelectInput (backend_x11->xdpy, stage_x11->xwin,
|
|
StructureNotifyMask |
|
|
FocusChangeMask |
|
|
ExposureMask |
|
|
EnterWindowMask | LeaveWindowMask |
|
|
PropertyChangeMask);
|
|
#ifdef USE_XINPUT
|
|
_clutter_x11_select_events (stage_x11->xwin);
|
|
#endif
|
|
}
|
|
else
|
|
XSelectInput (backend_x11->xdpy, stage_x11->xwin,
|
|
StructureNotifyMask |
|
|
FocusChangeMask |
|
|
ExposureMask |
|
|
PointerMotionMask |
|
|
KeyPressMask | KeyReleaseMask |
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
EnterWindowMask | LeaveWindowMask |
|
|
PropertyChangeMask);
|
|
}
|
|
|
|
/* no user resize... */
|
|
clutter_stage_x11_fix_window_size (stage_x11,
|
|
stage_x11->xwin_width,
|
|
stage_x11->xwin_height);
|
|
clutter_stage_x11_set_wm_protocols (stage_x11);
|
|
|
|
return clutter_stage_egl_parent_iface->realize (stage_window);
|
|
}
|
|
|
|
#else /* COGL_HAS_XLIB_SUPPORT */
|
|
|
|
static void
|
|
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
|
|
{
|
|
}
|
|
|
|
static gboolean
|
|
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
|
{
|
|
/* the EGL surface is created by the backend */
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
|
|
gboolean fullscreen)
|
|
{
|
|
g_warning ("Stage of type '%s' do not support ClutterStage::set_fullscreen",
|
|
G_OBJECT_TYPE_NAME (stage_window));
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_set_title (ClutterStageWindow *stage_window,
|
|
const gchar *title)
|
|
{
|
|
g_warning ("Stage of type '%s' do not support ClutterStage::set_title",
|
|
G_OBJECT_TYPE_NAME (stage_window));
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_set_cursor_visible (ClutterStageWindow *stage_window,
|
|
gboolean cursor_visible)
|
|
{
|
|
g_warning ("Stage of type '%s' do not support ClutterStage::set_cursor_visible",
|
|
G_OBJECT_TYPE_NAME (stage_window));
|
|
}
|
|
|
|
static ClutterActor *
|
|
clutter_stage_egl_get_wrapper (ClutterStageWindow *stage_window)
|
|
{
|
|
return CLUTTER_ACTOR (CLUTTER_STAGE_EGL (stage_window)->wrapper);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_show (ClutterStageWindow *stage_window,
|
|
gboolean do_raise)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
|
|
|
clutter_actor_map (CLUTTER_ACTOR (stage_egl->wrapper));
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_hide (ClutterStageWindow *stage_window)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
|
|
|
clutter_actor_unmap (CLUTTER_ACTOR (stage_egl->wrapper));
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_get_geometry (ClutterStageWindow *stage_window,
|
|
ClutterGeometry *geometry)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
|
ClutterBackendEGL *backend_egl = stage_egl->backend;
|
|
|
|
if (geometry)
|
|
{
|
|
geometry->x = geometry->y = 0;
|
|
|
|
geometry->width = backend_egl->surface_width;
|
|
geometry->height = backend_egl->surface_height;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_resize (ClutterStageWindow *stage_window,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
}
|
|
|
|
#endif /* COGL_HAS_XLIB_SUPPORT */
|
|
|
|
static void
|
|
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
|
{
|
|
#ifdef COGL_HAS_X11_SUPPORT
|
|
clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
|
|
|
|
iface->realize = clutter_stage_egl_realize;
|
|
iface->unrealize = clutter_stage_egl_unrealize;
|
|
|
|
/* the rest is inherited from ClutterStageX11 */
|
|
|
|
#else /* COGL_HAS_X11_SUPPORT */
|
|
|
|
iface->realize = clutter_stage_egl_realize;
|
|
iface->unrealize = clutter_stage_egl_unrealize;
|
|
iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
|
|
iface->set_title = clutter_stage_egl_set_title;
|
|
iface->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
|
|
iface->get_wrapper = clutter_stage_egl_get_wrapper;
|
|
iface->get_geometry = clutter_stage_egl_get_geometry;
|
|
iface->resize = clutter_stage_egl_resize;
|
|
iface->show = clutter_stage_egl_show;
|
|
iface->hide = clutter_stage_egl_hide;
|
|
|
|
#endif /* COGL_HAS_X11_SUPPORT */
|
|
}
|
|
|
|
#ifdef COGL_HAS_X11_SUPPORT
|
|
static void
|
|
clutter_stage_egl_dispose (GObject *gobject)
|
|
{
|
|
G_OBJECT_CLASS (_clutter_stage_egl_parent_class)->dispose (gobject);
|
|
}
|
|
|
|
static void
|
|
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
gobject_class->dispose = clutter_stage_egl_dispose;
|
|
}
|
|
|
|
static void
|
|
_clutter_stage_egl_init (ClutterStageEGL *stage)
|
|
{
|
|
stage->egl_surface = EGL_NO_SURFACE;
|
|
}
|
|
|
|
#else /* COGL_HAS_X11_SUPPORT */
|
|
|
|
static void
|
|
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
|
{
|
|
}
|
|
|
|
static void
|
|
_clutter_stage_egl_init (ClutterStageEGL *stage)
|
|
{
|
|
/* Without X we only support one surface and that is associated
|
|
* with the backend directly instead of the stage */
|
|
}
|
|
|
|
#endif /* COGL_HAS_X11_SUPPORT */
|
|
|
|
void
|
|
_clutter_stage_egl_redraw (ClutterStageEGL *stage_egl,
|
|
ClutterStage *stage)
|
|
{
|
|
ClutterBackend *backend = clutter_get_default_backend ();
|
|
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
ClutterActor *wrapper;
|
|
EGLSurface egl_surface;
|
|
#ifdef COGL_HAS_X11_SUPPORT
|
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
|
|
|
|
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
|
|
egl_surface = stage_egl->egl_surface;
|
|
#else
|
|
wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
|
|
/* Without X we only support one surface and that is associated
|
|
* with the backend directly instead of the stage */
|
|
egl_surface = backend_egl->egl_surface;
|
|
#endif
|
|
|
|
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
|
|
cogl_flush ();
|
|
|
|
eglSwapBuffers (backend_egl->edpy, egl_surface);
|
|
}
|