diff --git a/ChangeLog b/ChangeLog index 1b3819d7e..a308dd3b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2008-04-13 Neil Roberts + + 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 * clutter/clutter-container.c: diff --git a/clutter/win32/clutter-backend-win32.c b/clutter/win32/clutter-backend-win32.c index 3de069f15..22a81ab8f 100644 --- a/clutter/win32/clutter-backend-win32.c +++ b/clutter/win32/clutter-backend-win32.c @@ -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); + + CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]", + g_type_name (G_OBJECT_TYPE (impl)), + impl); - wglMakeCurrent (stage_win32->client_dc, - backend_win32->gl_context); + 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)) diff --git a/clutter/win32/clutter-event-win32.c b/clutter/win32/clutter-event-win32.c index df3028659..9a46a5491 100644 --- a/clutter/win32/clutter-event-win32.c +++ b/clutter/win32/clutter-event-win32.c @@ -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; } diff --git a/clutter/win32/clutter-stage-win32.c b/clutter/win32/clutter-stage-win32.c index 171776ae0..54c8cef23 100644 --- a/clutter/win32/clutter-stage-win32.c +++ b/clutter/win32/clutter-stage-win32.c @@ -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 -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); } diff --git a/clutter/win32/clutter-stage-win32.h b/clutter/win32/clutter-stage-win32.h index 79e09a1d7..eff18cd1f 100644 --- a/clutter/win32/clutter-stage-win32.h +++ b/clutter/win32/clutter-stage-win32.h @@ -22,7 +22,7 @@ #ifndef __CLUTTER_STAGE_WIN32_H__ #define __CLUTTER_STAGE_WIN32_H__ -#include +#include #include #include @@ -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;