Upgraded the Win32 backend to work with the multi-stage

subclassing code.

	* clutter/win32/clutter-stage-win32.h: 
	* clutter/win32/clutter-stage-win32.c: Now inherits from
	ClutterGroup and implements ClutterStageWindow instead of
	inheriting directly from ClutterStage.

	* clutter/win32/clutter-event-win32.c (message_translate): Now
	takes an extra parameter to return whether DefWindowProc should be
	called. This is needed to prevent the default WM_CLOSE handler
	from destroying the window.

	* clutter/win32/clutter-backend-win32.c
	(clutter_backend_win32_dispose): Destroy all of the stages using
	g_slist_foreach as per bug #871. Now also destroys the GL context.
	(clutter_backend_win32_get_features): Added assertions to ensure
	there is a valid GL context.
	(clutter_backend_win32_ensure_context): Accepts NULL stage. Gets
	implementation pointer from the stage.
This commit is contained in:
Neil Roberts 2008-04-13 08:43:32 +00:00
parent bf48bd1f55
commit 0b8a500fca
5 changed files with 250 additions and 75 deletions

View File

@ -1,3 +1,26 @@
2008-04-13 Neil Roberts <neil@o-hand.com>
Upgraded the Win32 backend to work with the multi-stage
subclassing code.
* clutter/win32/clutter-stage-win32.h:
* clutter/win32/clutter-stage-win32.c: Now inherits from
ClutterGroup and implements ClutterStageWindow instead of
inheriting directly from ClutterStage.
* clutter/win32/clutter-event-win32.c (message_translate): Now
takes an extra parameter to return whether DefWindowProc should be
called. This is needed to prevent the default WM_CLOSE handler
from destroying the window.
* clutter/win32/clutter-backend-win32.c
(clutter_backend_win32_dispose): Destroy all of the stages using
g_slist_foreach as per bug #871. Now also destroys the GL context.
(clutter_backend_win32_get_features): Added assertions to ensure
there is a valid GL context.
(clutter_backend_win32_ensure_context): Accepts NULL stage. Gets
implementation pointer from the stage.
2008-04-11 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-container.c:

View File

@ -33,6 +33,7 @@
#include "../clutter-main.h"
#include "../clutter-debug.h"
#include "../clutter-private.h"
#include "../clutter-version.h"
#include "cogl.h"
@ -100,22 +101,27 @@ clutter_backend_win32_dispose (GObject *gobject)
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (gobject);
ClutterMainContext *context;
ClutterStageManager *stage_manager;
GSList *l;
CLUTTER_NOTE (BACKEND, "Disposing the of stages");
context = clutter_context_get_default ();
stage_manager = context->stage_manager;
for (l = stage_manager->stages; l; l = l->next)
{
ClutterActor *stage = CLUTTER_ACTOR (l->data);
clutter_actor_destroy (stage);
}
/* Destroy all of the stages. g_slist_foreach is used because the
finalizer for the stages will remove the stage from the
stage_manager's list and g_slist_foreach has some basic
protection against this */
g_slist_foreach (stage_manager->stages, (GFunc) clutter_actor_destroy, NULL);
CLUTTER_NOTE (BACKEND, "Removing the event source");
_clutter_backend_win32_events_uninit (CLUTTER_BACKEND (backend_win32));
if (backend_win32->gl_context)
{
wglDeleteContext (backend_win32->gl_context);
backend_win32->gl_context = NULL;
}
G_OBJECT_CLASS (clutter_backend_win32_parent_class)->dispose (gobject);
}
@ -152,14 +158,21 @@ check_vblank_env (const char *name)
ClutterFeatureFlags
clutter_backend_win32_get_features (ClutterBackend *backend)
{
ClutterFeatureFlags flags;
const gchar *extensions;
SwapIntervalProc swap_interval;
ClutterFeatureFlags flags;
const gchar *extensions;
SwapIntervalProc swap_interval;
ClutterBackendWin32 *backend_win32;
/* FIXME: we really need to check if gl context is set */
extensions = glGetString (GL_EXTENSIONS);
/* this will make sure that the GL context exists and is bound to a
drawable */
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
g_return_val_if_fail (backend_win32->gl_context != NULL, 0);
g_return_val_if_fail (wglGetCurrentDC () != NULL, 0);
CLUTTER_NOTE (BACKEND, "Checking features\n"
"GL_VENDOR: %s\n"
"GL_RENDERER: %s\n"
@ -217,24 +230,70 @@ static void
clutter_backend_win32_ensure_context (ClutterBackend *backend,
ClutterStage *stage)
{
ClutterBackendWin32 *backend_win32;
ClutterStageWin32 *stage_win32;
if (stage == NULL)
{
CLUTTER_NOTE (MULTISTAGE, "Clearing all context");
stage_win32 = CLUTTER_STAGE_WIN32 (stage);
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
wglMakeCurrent (NULL, NULL);
}
else
{
ClutterBackendWin32 *backend_win32;
ClutterStageWin32 *stage_win32;
ClutterStageWindow *impl;
CLUTTER_NOTE (MULTISTAGE, "setting context for stage:%p", stage );
impl = _clutter_stage_get_window (stage);
g_return_if_fail (impl != NULL);
wglMakeCurrent (stage_win32->client_dc,
backend_win32->gl_context);
CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]",
g_type_name (G_OBJECT_TYPE (impl)),
impl);
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
stage_win32 = CLUTTER_STAGE_WIN32 (impl);
/* no GL context to set */
if (backend_win32->gl_context == NULL)
return;
/* we might get here inside the final dispose cycle, so we
* need to handle this gracefully
*/
if (stage_win32->client_dc == NULL)
{
CLUTTER_NOTE (MULTISTAGE,
"Received a stale stage, clearing all context");
wglMakeCurrent (NULL, NULL);
}
else
{
CLUTTER_NOTE (BACKEND,
"MakeCurrent window %p, context %p",
stage_win32->hwnd,
backend_win32->gl_context);
wglMakeCurrent (stage_win32->client_dc,
backend_win32->gl_context);
}
}
}
static void
clutter_backend_win32_redraw (ClutterBackend *backend,
ClutterStage *stage)
{
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage);
ClutterStageWin32 *stage_win32;
ClutterStageWindow *impl;
impl = _clutter_stage_get_window (stage);
if (impl == NULL)
return;
g_return_if_fail (CLUTTER_IS_STAGE_WIN32 (impl));
stage_win32 = CLUTTER_STAGE_WIN32 (impl);
/* this will cause the stage implementation to be painted */
clutter_actor_paint (CLUTTER_ACTOR (stage));
if (stage_win32->client_dc)
@ -243,21 +302,33 @@ clutter_backend_win32_redraw (ClutterBackend *backend,
static ClutterActor *
clutter_backend_win32_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
ClutterStageWin32 *stage_win32;
ClutterActor *stage;
stage = g_object_new (CLUTTER_TYPE_STAGE_WIN32, NULL);
CLUTTER_NOTE (BACKEND, "Creating stage of type `%s'",
g_type_name (CLUTTER_STAGE_TYPE));
stage = g_object_new (CLUTTER_STAGE_TYPE, NULL);
/* copy backend data into the stage */
stage_win32 = CLUTTER_STAGE_WIN32 (stage);
stage_win32->backend = backend_win32;
stage_win32->wrapper = wrapper;
/* set the pointer back into the wrapper */
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
/* needed ? */
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
/* FIXME - is this needed? we should call realize inside the clutter
* init sequence for the default stage, and let the usual realization
* sequence be used for any other stage
*/
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))

View File

@ -301,11 +301,13 @@ get_key_modifier_state (const BYTE *key_states)
static gboolean
message_translate (ClutterBackend *backend,
ClutterEvent *event,
const MSG *msg)
const MSG *msg,
gboolean *call_def_window_proc)
{
ClutterBackendWin32 *backend_win32;
ClutterStageWin32 *stage_win32;
ClutterStage *stage;
ClutterStageWindow *impl;
gboolean res;
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
@ -315,7 +317,8 @@ message_translate (ClutterBackend *backend,
if (stage == NULL)
return FALSE;
stage_win32 = CLUTTER_STAGE_WIN32 (stage);
impl = _clutter_stage_get_window (stage);
stage_win32 = CLUTTER_STAGE_WIN32 (impl);
event->any.stage = stage;
@ -404,6 +407,16 @@ message_translate (ClutterBackend *backend,
event->type = CLUTTER_DESTROY_NOTIFY;
break;
case WM_CLOSE:
CLUTTER_NOTE (EVENT, "WM_CLOSE");
event->type = CLUTTER_DELETE;
/* The default window proc will destroy the window so we want to
prevent this to allow applications to optionally destroy the
window themselves */
if (call_def_window_proc)
*call_def_window_proc = FALSE;
break;
case WM_LBUTTONDOWN:
make_button_event (msg, event, 1, 1, FALSE);
break;
@ -552,6 +565,15 @@ message_translate (ClutterBackend *backend,
}
break;
case WM_GETMINMAXINFO:
{
MINMAXINFO *min_max_info = (MINMAXINFO *) msg->lParam;
_clutter_stage_win32_get_min_max_info (stage_win32, min_max_info);
if (call_def_window_proc)
*call_def_window_proc = FALSE;
}
break;
default:
/* ignore every other message */
res = FALSE;
@ -567,6 +589,7 @@ _clutter_stage_win32_window_proc (HWND hwnd, UINT umsg,
{
ClutterStageWin32 *stage_win32
= (ClutterStageWin32 *) GetWindowLongPtrW (hwnd, 0);
gboolean call_def_window_proc = TRUE;
/* Ignore any messages before SetWindowLongPtr has been called to
set the stage */
@ -590,25 +613,18 @@ _clutter_stage_win32_window_proc (HWND hwnd, UINT umsg,
msg.pt.x = (SHORT) LOWORD (message_pos);
msg.pt.y = (SHORT) HIWORD (message_pos);
/* Some messages are handled here specially outside of
message_translate so that DefWindowProc can be overridden */
if (umsg == WM_GETMINMAXINFO)
{
MINMAXINFO *min_max_info = (MINMAXINFO *) lparam;
_clutter_stage_win32_get_min_max_info (stage_win32, min_max_info);
return 0;
}
else
{
event = clutter_event_new (CLUTTER_NOTHING);
event = clutter_event_new (CLUTTER_NOTHING);
if (message_translate (CLUTTER_BACKEND (backend_win32), event, &msg))
/* push directly here to avoid copy of queue_put */
g_queue_push_head (clutter_context->events_queue, event);
else
clutter_event_free (event);
}
if (message_translate (CLUTTER_BACKEND (backend_win32), event,
&msg, &call_def_window_proc))
/* push directly here to avoid copy of queue_put */
g_queue_push_head (clutter_context->events_queue, event);
else
clutter_event_free (event);
}
return DefWindowProcW (hwnd, umsg, wparam, lparam);
if (call_def_window_proc)
return DefWindowProcW (hwnd, umsg, wparam, lparam);
else
return 0;
}

View File

@ -27,6 +27,7 @@
#include "clutter-stage-win32.h"
#include "clutter-win32.h"
#include "../clutter-stage-window.h"
#include "../clutter-main.h"
#include "../clutter-feature.h"
#include "../clutter-color.h"
@ -36,13 +37,21 @@
#include "../clutter-private.h"
#include "../clutter-debug.h"
#include "../clutter-units.h"
#include "../clutter-shader.h"
#include "../clutter-stage.h"
#include "cogl.h"
#include <windows.h>
G_DEFINE_TYPE (ClutterStageWin32, clutter_stage_win32, CLUTTER_TYPE_STAGE);
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageWin32,
clutter_stage_win32,
CLUTTER_TYPE_GROUP,
G_IMPLEMENT_INTERFACE
(CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
static void
clutter_stage_win32_show (ClutterActor *actor)
@ -122,7 +131,7 @@ get_full_window_pos (ClutterStageWin32 *stage_win32,
int *xpos_out, int *ypos_out)
{
gboolean resizable
= clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_win32));
= clutter_stage_get_user_resizable (stage_win32->wrapper);
/* The window position passed to CreateWindow includes the window
decorations */
*xpos_out = xpos_in - GetSystemMetrics (resizable ? SM_CXSIZEFRAME
@ -138,7 +147,7 @@ get_full_window_size (ClutterStageWin32 *stage_win32,
int *width_out, int *height_out)
{
gboolean resizable
= clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_win32));
= clutter_stage_get_user_resizable (stage_win32->wrapper);
/* The window size passed to CreateWindow includes the window
decorations */
*width_out = width_in + GetSystemMetrics (resizable ? SM_CXSIZEFRAME
@ -154,7 +163,7 @@ _clutter_stage_win32_get_min_max_info (ClutterStageWin32 *stage_win32,
{
/* If the window isn't resizable then set the max and min size to
the current size */
if (!clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_win32)))
if (!clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_win32->wrapper)))
{
int full_width, full_height;
get_full_window_size (stage_win32,
@ -214,7 +223,8 @@ clutter_stage_win32_request_coords (ClutterActor *self,
change_flags);
}
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_SYNC_MATRICES);
CLUTTER_SET_PRIVATE_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_SYNC_MATRICES);
}
CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)
@ -222,10 +232,10 @@ clutter_stage_win32_request_coords (ClutterActor *self,
}
static void
clutter_stage_win32_set_title (ClutterStage *stage,
const gchar *title)
clutter_stage_win32_set_title (ClutterStageWindow *stage_window,
const gchar *title)
{
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage);
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
wchar_t *wtitle;
/* Empty window titles not allowed, so set it to just a period. */
@ -240,36 +250,44 @@ clutter_stage_win32_set_title (ClutterStage *stage,
static LONG
get_window_style (ClutterStageWin32 *stage_win32)
{
ClutterStage *wrapper = stage_win32->wrapper;
/* Fullscreen mode shouldn't have any borders */
if ((stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN))
return WS_POPUP;
/* Otherwise it's an overlapped window but if it isn't resizable
then it shouldn't have a thick frame */
else if (clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_win32)))
else if (clutter_stage_get_user_resizable (wrapper))
return WS_OVERLAPPEDWINDOW;
else
return WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME;
}
static void
clutter_stage_win32_set_user_resize (ClutterStage *stage,
gboolean value)
clutter_stage_win32_set_user_resize (ClutterStageWindow *stage_window,
gboolean value)
{
HWND hwnd = CLUTTER_STAGE_WIN32 (stage)->hwnd;
HWND hwnd = CLUTTER_STAGE_WIN32 (stage_window)->hwnd;
LONG old_style = GetWindowLongW (hwnd, GWL_STYLE);
/* Update the window style but preserve the visibility */
SetWindowLongW (hwnd, GWL_STYLE,
get_window_style (CLUTTER_STAGE_WIN32 (stage))
get_window_style (CLUTTER_STAGE_WIN32 (stage_window))
| (old_style & WS_VISIBLE));
}
static void
clutter_stage_win32_set_fullscreen (ClutterStage *stage,
gboolean value)
static ClutterActor *
clutter_stage_win32_get_wrapper (ClutterStageWindow *stage_window)
{
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage);
HWND hwnd = CLUTTER_STAGE_WIN32 (stage)->hwnd;
return CLUTTER_ACTOR (CLUTTER_STAGE_WIN32 (stage_window)->wrapper);
}
static void
clutter_stage_win32_set_fullscreen (ClutterStageWindow *stage_window,
gboolean value)
{
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
HWND hwnd = CLUTTER_STAGE_WIN32 (stage_window)->hwnd;
LONG old_style = GetWindowLongW (hwnd, GWL_STYLE);
ClutterStageStateEvent event;
@ -316,13 +334,14 @@ clutter_stage_win32_set_fullscreen (ClutterStage *stage,
SWP_NOZORDER);
}
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
CLUTTER_SET_PRIVATE_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_SYNC_MATRICES);
}
/* Report the state change */
memset (&event, 0, sizeof (event));
event.type = CLUTTER_STAGE_STATE;
event.stage = CLUTTER_STAGE (stage_win32);
event.stage = CLUTTER_STAGE (stage_win32->wrapper);
event.new_state = stage_win32->state;
event.changed_mask = CLUTTER_STAGE_STATE_FULLSCREEN;
clutter_event_put ((ClutterEvent *) &event);
@ -407,6 +426,8 @@ clutter_stage_win32_realize (ClutterActor *actor)
if (window_class == 0)
{
g_critical ("Unable to register window class");
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
@ -449,6 +470,8 @@ clutter_stage_win32_realize (ClutterActor *actor)
if (stage_win32->hwnd == NULL)
{
g_critical ("Unable to create stage window");
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
@ -490,6 +513,8 @@ clutter_stage_win32_realize (ClutterActor *actor)
|| !SetPixelFormat (stage_win32->client_dc, pf, &pfd))
{
g_critical ("Unable to find suitable GL pixel format");
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
@ -501,24 +526,30 @@ clutter_stage_win32_realize (ClutterActor *actor)
if (backend_win32->gl_context == NULL)
{
g_critical ("Unable to create suitable GL context");
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
}
CLUTTER_NOTE (GL, "wglMakeCurrent");
clutter_stage_ensure_current (CLUTTER_STAGE (stage_win32));
/* below will call wglMakeCurrent */
CLUTTER_ACTOR_SET_FLAGS (stage_win32->wrapper, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_SET_FLAGS (stage_win32, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (stage_win32->wrapper);
if (!clutter_stage_win32_check_gl_version ())
{
g_critical ("OpenGL version number is too low");
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
/* Make sure the viewport gets set up correctly */
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES);
CLUTTER_SET_PRIVATE_FLAGS (stage_win32->wrapper,
CLUTTER_ACTOR_SYNC_MATRICES);
}
static void
@ -526,7 +557,18 @@ clutter_stage_win32_unrealize (ClutterActor *actor)
{
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (actor);
wglMakeCurrent (NULL, NULL);
CLUTTER_NOTE (BACKEND, "Unrealizing stage");
/* Chain up so all children get unrealized, needed to move texture
* data across contexts
*/
CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)->unrealize (actor);
/* Unrealize all shaders, since the GL context is going away */
_clutter_shader_release_all ();
/* As unrealised the context will now get cleared */
clutter_stage_ensure_current (stage_win32->wrapper);
if (stage_win32->client_dc)
{
@ -536,6 +578,11 @@ clutter_stage_win32_unrealize (ClutterActor *actor)
if (stage_win32->hwnd)
{
/* Drop the pointer to this stage in the window so that any
further messages won't be processed. The stage might be being
destroyed so otherwise the messages would be handled with an
invalid stage instance */
SetWindowLongPtrW (stage_win32->hwnd, 0, (LONG_PTR) 0);
DestroyWindow (stage_win32->hwnd);
stage_win32->hwnd = NULL;
}
@ -557,7 +604,6 @@ clutter_stage_win32_class_init (ClutterStageWin32Class *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass);
gobject_class->dispose = clutter_stage_win32_dispose;
@ -567,10 +613,6 @@ clutter_stage_win32_class_init (ClutterStageWin32Class *klass)
actor_class->query_coords = clutter_stage_win32_query_coords;
actor_class->realize = clutter_stage_win32_realize;
actor_class->unrealize = clutter_stage_win32_unrealize;
stage_class->set_title = clutter_stage_win32_set_title;
stage_class->set_user_resize = clutter_stage_win32_set_user_resize;
stage_class->set_fullscreen = clutter_stage_win32_set_fullscreen;
}
static void
@ -584,6 +626,19 @@ clutter_stage_win32_init (ClutterStageWin32 *stage)
stage->win_height = 480;
stage->backend = NULL;
stage->scroll_pos = 0;
stage->wrapper = NULL;
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IS_TOPLEVEL);
}
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
iface->get_wrapper = clutter_stage_win32_get_wrapper;
iface->set_title = clutter_stage_win32_set_title;
iface->set_fullscreen = clutter_stage_win32_set_fullscreen;
iface->set_user_resizable = clutter_stage_win32_set_user_resize;
}
/**
@ -599,9 +654,15 @@ clutter_stage_win32_init (ClutterStageWin32 *stage)
HWND
clutter_win32_get_stage_window (ClutterStage *stage)
{
g_return_val_if_fail (CLUTTER_IS_STAGE_WIN32 (stage), NULL);
ClutterStageWindow *impl;
return CLUTTER_STAGE_WIN32 (stage)->hwnd;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
impl = _clutter_stage_get_window (stage);
g_return_val_if_fail (CLUTTER_IS_STAGE_WIN32 (impl), NULL);
return CLUTTER_STAGE_WIN32 (impl)->hwnd;
}
/**
@ -624,7 +685,7 @@ clutter_win32_get_stage_from_window (HWND hwnd)
== clutter_stage_win32_get_window_class ())
/* If it is there should be a pointer to the stage in the window
extra data */
return (ClutterStage *) GetWindowLongPtrW (hwnd, 0);
return CLUTTER_STAGE_WIN32 (GetWindowLongPtrW (hwnd, 0))->wrapper;
else
return NULL;
}
@ -633,12 +694,14 @@ void
clutter_stage_win32_map (ClutterStageWin32 *stage_win32)
{
CLUTTER_ACTOR_SET_FLAGS (stage_win32, CLUTTER_ACTOR_MAPPED);
CLUTTER_ACTOR_SET_FLAGS (stage_win32->wrapper, CLUTTER_ACTOR_MAPPED);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_win32));
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_win32->wrapper));
}
void
clutter_stage_win32_unmap (ClutterStageWin32 *stage_win32)
{
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32, CLUTTER_ACTOR_MAPPED);
CLUTTER_ACTOR_UNSET_FLAGS (stage_win32->wrapper, CLUTTER_ACTOR_MAPPED);
}

View File

@ -22,7 +22,7 @@
#ifndef __CLUTTER_STAGE_WIN32_H__
#define __CLUTTER_STAGE_WIN32_H__
#include <glib-object.h>
#include <clutter/clutter-group.h>
#include <clutter/clutter-stage.h>
#include <windows.h>
@ -42,7 +42,7 @@ typedef struct _ClutterStageWin32Class ClutterStageWin32Class;
struct _ClutterStageWin32
{
ClutterStage parent_instance;
ClutterGroup parent_instance;
HWND hwnd;
HDC client_dc;
@ -55,11 +55,13 @@ struct _ClutterStageWin32
ClutterBackendWin32 *backend;
ClutterStageState state;
ClutterStage *wrapper;
};
struct _ClutterStageWin32Class
{
ClutterStageClass parent_class;
ClutterGroupClass parent_class;
};
GType clutter_stage_win32_get_type (void) G_GNUC_CONST;