From 1a263dca5c555aadfa61c639e2bf5289d4531aa2 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Sun, 30 Mar 2008 16:51:01 +0000 Subject: [PATCH] 2008-03-30 Neil Roberts * clutter/win32/clutter-win32.h: * clutter/win32/clutter-stage-win32.h: * clutter/win32/clutter-stage-win32.c: * clutter/win32/clutter-event-win32.c: * clutter/win32/clutter-backend-win32.h: * clutter/win32/clutter-backend-win32.c: Upgraded for multi-stage support. * clutter/win32/clutter-stage-win32.c (clutter_stage_win32_request_coords): Fixed so that it doesn't set the position or size if it hasn't changed. This was causing problems when the window was resized using the top left corner. In that case the window receives resize and move messages separately which caused the window to flash at a different size or position while one message was handled before the other. (clutter_stage_win32_realize): Added PFD_GENERIC_ACCELERATED to the list of pixel format flags to force it to use hardware acceleration. 2008-03-30 Neil Roberts * clutter-sections.txt: Added clutter_win32_get_stage_from_window --- ChangeLog | 21 +++++ clutter/win32/clutter-backend-win32.c | 108 ++++++++++++++------------ clutter/win32/clutter-backend-win32.h | 6 +- clutter/win32/clutter-event-win32.c | 14 ++-- clutter/win32/clutter-stage-win32.c | 78 +++++++++++++------ clutter/win32/clutter-stage-win32.h | 3 - clutter/win32/clutter-win32.h | 3 +- doc/reference/ChangeLog | 4 + doc/reference/clutter-sections.txt | 1 + 9 files changed, 148 insertions(+), 90 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6336e2358..49de87a29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2008-03-30 Neil Roberts + + * clutter/win32/clutter-win32.h: + * clutter/win32/clutter-stage-win32.h: + * clutter/win32/clutter-stage-win32.c: + * clutter/win32/clutter-event-win32.c: + * clutter/win32/clutter-backend-win32.h: + * clutter/win32/clutter-backend-win32.c: + Upgraded for multi-stage support. + + * clutter/win32/clutter-stage-win32.c + (clutter_stage_win32_request_coords): Fixed so that it doesn't set + the position or size if it hasn't changed. This was causing + problems when the window was resized using the top left corner. In + that case the window receives resize and move messages separately + which caused the window to flash at a different size or position + while one message was handled before the other. + (clutter_stage_win32_realize): Added PFD_GENERIC_ACCELERATED to + the list of pixel format flags to force it to use hardware + acceleration. + 2008-03-28 Matthew Allum * clutter/Makefile.am: diff --git a/clutter/win32/clutter-backend-win32.c b/clutter/win32/clutter-backend-win32.c index b298e146f..9b5d938ad 100644 --- a/clutter/win32/clutter-backend-win32.c +++ b/clutter/win32/clutter-backend-win32.c @@ -66,14 +66,6 @@ clutter_backend_win32_init_events (ClutterBackend *backend) _clutter_backend_win32_events_init (backend); } -ClutterActor * -clutter_backend_win32_get_stage (ClutterBackend *backend) -{ - ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend); - - return backend_win32->stage; -} - static const GOptionEntry entries[] = { { @@ -104,18 +96,19 @@ static void clutter_backend_win32_dispose (GObject *gobject) { ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (gobject); + ClutterMainContext *context; + ClutterStageManager *stage_manager; + GSList *l; - if (backend_win32->stage) + 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) { - CLUTTER_NOTE (BACKEND, "Disposing the main stage"); - - /* we unset the private flag on the stage so we can safely - * destroy it without a warning from clutter_actor_destroy() - */ - CLUTTER_UNSET_PRIVATE_FLAGS (backend_win32->stage, - CLUTTER_ACTOR_IS_TOPLEVEL); - clutter_actor_destroy (backend_win32->stage); - backend_win32->stage = NULL; + ClutterActor *stage = CLUTTER_ACTOR (l->data); + clutter_actor_destroy (stage); } CLUTTER_NOTE (BACKEND, "Removing the event source"); @@ -175,7 +168,9 @@ clutter_backend_win32_get_features (ClutterBackend *backend) glGetString (GL_VERSION), extensions); - flags = CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR; + flags = CLUTTER_FEATURE_STAGE_USER_RESIZE + | CLUTTER_FEATURE_STAGE_CURSOR + | CLUTTER_FEATURE_STAGE_MULTIPLE; /* If the VBlank should be left at the default or it has been disabled elsewhere (eg NVIDIA) then don't bother trying to check @@ -217,52 +212,61 @@ clutter_backend_win32_get_features (ClutterBackend *backend) } static void -clutter_backend_win32_redraw (ClutterBackend *backend) +clutter_backend_win32_ensure_context (ClutterBackend *backend, + ClutterStage *stage) { - ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend); - ClutterStageWin32 *stage_win32; + ClutterBackendWin32 *backend_win32; + ClutterStageWin32 *stage_win32; - stage_win32 = CLUTTER_STAGE_WIN32 (backend_win32->stage); + stage_win32 = CLUTTER_STAGE_WIN32 (stage); + backend_win32 = CLUTTER_BACKEND_WIN32 (backend); - clutter_actor_paint (CLUTTER_ACTOR (stage_win32)); + CLUTTER_NOTE (MULTISTAGE, "setting context for stage:%p", stage ); + + 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); + + clutter_actor_paint (CLUTTER_ACTOR (stage)); if (stage_win32->client_dc) SwapBuffers (stage_win32->client_dc); } -static gboolean -clutter_backend_win32_init_stage (ClutterBackend *backend, - GError **error) +static ClutterActor * +clutter_backend_win32_create_stage (ClutterBackend *backend, + GError **error) { ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend); + ClutterStageWin32 *stage_win32; + ClutterActor *stage; - if (!backend_win32->stage) - { - ClutterStageWin32 *stage_win32; - ClutterActor *stage; + stage = g_object_new (CLUTTER_TYPE_STAGE_WIN32, NULL); - stage = g_object_new (CLUTTER_TYPE_STAGE_WIN32, NULL); + /* copy backend data into the stage */ + stage_win32 = CLUTTER_STAGE_WIN32 (stage); + stage_win32->backend = backend_win32; - /* copy backend data into the stage */ - stage_win32 = CLUTTER_STAGE_WIN32 (stage); - stage_win32->backend = backend_win32; + /* needed ? */ + g_object_set_data (G_OBJECT (stage), "clutter-backend", backend); - g_object_set_data (G_OBJECT (stage), "clutter-backend", backend); + clutter_actor_realize (stage); - backend_win32->stage = g_object_ref_sink (stage); - } - - clutter_actor_realize (backend_win32->stage); - - if (!CLUTTER_ACTOR_IS_REALIZED (backend_win32->stage)) + if (!CLUTTER_ACTOR_IS_REALIZED (stage)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_INTERNAL, "Unable to realize the main stage"); - return FALSE; + return NULL; } - return TRUE; + return stage; } static void @@ -275,13 +279,13 @@ clutter_backend_win32_class_init (ClutterBackendWin32Class *klass) gobject_class->dispose = clutter_backend_win32_dispose; gobject_class->finalize = clutter_backend_win32_finalize; - backend_class->pre_parse = clutter_backend_win32_pre_parse; - backend_class->init_events = clutter_backend_win32_init_events; - backend_class->init_stage = clutter_backend_win32_init_stage; - backend_class->get_stage = clutter_backend_win32_get_stage; - backend_class->add_options = clutter_backend_win32_add_options; - backend_class->get_features = clutter_backend_win32_get_features; - backend_class->redraw = clutter_backend_win32_redraw; + backend_class->pre_parse = clutter_backend_win32_pre_parse; + backend_class->init_events = clutter_backend_win32_init_events; + backend_class->create_stage = clutter_backend_win32_create_stage; + backend_class->add_options = clutter_backend_win32_add_options; + backend_class->get_features = clutter_backend_win32_get_features; + backend_class->redraw = clutter_backend_win32_redraw; + backend_class->ensure_context = clutter_backend_win32_ensure_context; } static void @@ -289,6 +293,8 @@ clutter_backend_win32_init (ClutterBackendWin32 *backend_win32) { ClutterBackend *backend = CLUTTER_BACKEND (backend_win32); + backend_win32->gl_context = NULL; + /* FIXME: get from GetSystemMetric? */ clutter_backend_set_double_click_time (backend, 250); clutter_backend_set_double_click_distance (backend, 5); diff --git a/clutter/win32/clutter-backend-win32.h b/clutter/win32/clutter-backend-win32.h index 649a3b14d..245bc1903 100644 --- a/clutter/win32/clutter-backend-win32.h +++ b/clutter/win32/clutter-backend-win32.h @@ -45,8 +45,7 @@ struct _ClutterBackendWin32 { ClutterBackend parent_instance; - /* main stage singleton */ - ClutterActor *stage; + HGLRC gl_context; GSource *event_source; }; @@ -61,9 +60,6 @@ void _clutter_backend_win32_events_uninit (ClutterBackend *backend); GType clutter_backend_win32_get_type (void) G_GNUC_CONST; -ClutterActor * -clutter_backend_win32_get_stage (ClutterBackend *backend); - void clutter_backend_win32_add_options (ClutterBackend *backend, GOptionGroup *group); diff --git a/clutter/win32/clutter-event-win32.c b/clutter/win32/clutter-event-win32.c index e85b0eb7a..df3028659 100644 --- a/clutter/win32/clutter-event-win32.c +++ b/clutter/win32/clutter-event-win32.c @@ -307,16 +307,17 @@ message_translate (ClutterBackend *backend, ClutterStageWin32 *stage_win32; ClutterStage *stage; gboolean res; - HWND stage_hwnd; backend_win32 = CLUTTER_BACKEND_WIN32 (backend); - stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend)); - stage_win32 = CLUTTER_STAGE_WIN32 (stage); - stage_hwnd = clutter_win32_get_stage_window (stage); /* Do further processing only on events for the stage window */ - if (stage_hwnd != msg->hwnd) + stage = clutter_win32_get_stage_from_window (msg->hwnd); + + if (stage == NULL) return FALSE; + stage_win32 = CLUTTER_STAGE_WIN32 (stage); + + event->any.stage = stage; res = TRUE; @@ -393,7 +394,8 @@ message_translate (ClutterBackend *backend, break; case WM_PAINT: - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_win32)); + CLUTTER_NOTE (MULTISTAGE, "expose for stage:%p, redrawing", stage); + clutter_redraw (stage); res = FALSE; break; diff --git a/clutter/win32/clutter-stage-win32.c b/clutter/win32/clutter-stage-win32.c index bd6fa18f5..171776ae0 100644 --- a/clutter/win32/clutter-stage-win32.c +++ b/clutter/win32/clutter-stage-win32.c @@ -36,6 +36,7 @@ #include "../clutter-private.h" #include "../clutter-debug.h" #include "../clutter-units.h" +#include "../clutter-stage.h" #include "cogl.h" @@ -171,18 +172,23 @@ clutter_stage_win32_request_coords (ClutterActor *self, ClutterActorBox *box) { ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (self); - gint new_xpos, new_ypos, new_width, new_height; + int change_flags = SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; new_xpos = CLUTTER_UNITS_TO_INT (MIN (box->x1, box->x2)); new_ypos = CLUTTER_UNITS_TO_INT (MIN (box->y1, box->y2)); new_width = ABS (CLUTTER_UNITS_TO_INT (box->x2 - box->x1)); new_height = ABS (CLUTTER_UNITS_TO_INT (box->y2 - box->y1)); - if ((new_width != stage_win32->win_width - || new_height != stage_win32->win_height - || new_xpos != stage_win32->win_xpos - || new_ypos != stage_win32->win_ypos) + if (new_width != stage_win32->win_width + || new_height != stage_win32->win_height) + change_flags &= ~SWP_NOSIZE; + + if (new_xpos != stage_win32->win_xpos + || new_ypos != stage_win32->win_ypos) + change_flags &= ~SWP_NOMOVE; + + if ((change_flags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE) /* Ignore size requests if we are in full screen mode */ && (stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN) == 0) { @@ -205,7 +211,7 @@ clutter_stage_win32_request_coords (ClutterActor *self, SetWindowPos (stage_win32->hwnd, NULL, full_xpos, full_ypos, full_width, full_height, - SWP_NOZORDER); + change_flags); } CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_SYNC_MATRICES); @@ -316,6 +322,7 @@ clutter_stage_win32_set_fullscreen (ClutterStage *stage, /* Report the state change */ memset (&event, 0, sizeof (event)); event.type = CLUTTER_STAGE_STATE; + event.stage = CLUTTER_STAGE (stage_win32); event.new_state = stage_win32->state; event.changed_mask = CLUTTER_STAGE_STATE_FULLSCREEN; clutter_event_put ((ClutterEvent *) &event); @@ -382,11 +389,14 @@ static void clutter_stage_win32_realize (ClutterActor *actor) { ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (actor); + ClutterBackendWin32 *backend_win32; PIXELFORMATDESCRIPTOR pfd; int pf; CLUTTER_NOTE (MISC, "Realizing main stage"); + backend_win32 = CLUTTER_BACKEND_WIN32 (clutter_get_default_backend ()); + if (stage_win32->hwnd == NULL) { ATOM window_class = clutter_stage_win32_get_window_class (); @@ -459,9 +469,6 @@ clutter_stage_win32_realize (ClutterActor *actor) SetWindowLongPtrW (stage_win32->hwnd, 0, (LONG_PTR) stage_win32); } - if (stage_win32->gl_context) - wglDeleteContext (stage_win32->gl_context); - if (stage_win32->client_dc) ReleaseDC (stage_win32->hwnd, stage_win32->client_dc); @@ -470,7 +477,8 @@ clutter_stage_win32_realize (ClutterActor *actor) memset (&pfd, 0, sizeof (pfd)); pfd.nSize = sizeof (pfd); pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL + | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cAlphaBits = 8; @@ -486,17 +494,21 @@ clutter_stage_win32_realize (ClutterActor *actor) return; } - stage_win32->gl_context = wglCreateContext (stage_win32->client_dc); - - if (stage_win32->gl_context == NULL) + if (backend_win32->gl_context == NULL) { - g_critical ("Unable to create suitable GL context"); - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; + backend_win32->gl_context = wglCreateContext (stage_win32->client_dc); + + if (backend_win32->gl_context == NULL) + { + g_critical ("Unable to create suitable GL context"); + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + return; + } } CLUTTER_NOTE (GL, "wglMakeCurrent"); - wglMakeCurrent (stage_win32->client_dc, stage_win32->gl_context); + + clutter_stage_ensure_current (CLUTTER_STAGE (stage_win32)); if (!clutter_stage_win32_check_gl_version ()) { @@ -516,12 +528,6 @@ clutter_stage_win32_unrealize (ClutterActor *actor) wglMakeCurrent (NULL, NULL); - if (stage_win32->gl_context != NULL) - { - wglDeleteContext (stage_win32->gl_context); - stage_win32->gl_context = NULL; - } - if (stage_win32->client_dc) { ReleaseDC (stage_win32->hwnd, stage_win32->client_dc); @@ -572,7 +578,6 @@ clutter_stage_win32_init (ClutterStageWin32 *stage) { stage->hwnd = NULL; stage->client_dc = NULL; - stage->gl_context = NULL; stage->win_xpos = 0; stage->win_ypos = 0; stage->win_width = 640; @@ -599,6 +604,31 @@ clutter_win32_get_stage_window (ClutterStage *stage) return CLUTTER_STAGE_WIN32 (stage)->hwnd; } +/** + * clutter_win32_get_stage_from_window: + * @hwnd: a window handle + * + * Gets the stage for a particular window. + * + * Return value: The stage or NULL if a stage does not exist for the + * window. + * + * Since: 0.8 + */ +ClutterStage * +clutter_win32_get_stage_from_window (HWND hwnd) +{ + /* Check whether the window handle is an instance of the stage + window class */ + if ((ATOM) GetClassLongPtrW (hwnd, GCW_ATOM) + == 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); + else + return NULL; +} + void clutter_stage_win32_map (ClutterStageWin32 *stage_win32) { diff --git a/clutter/win32/clutter-stage-win32.h b/clutter/win32/clutter-stage-win32.h index 4a195af3e..79e09a1d7 100644 --- a/clutter/win32/clutter-stage-win32.h +++ b/clutter/win32/clutter-stage-win32.h @@ -46,7 +46,6 @@ struct _ClutterStageWin32 HWND hwnd; HDC client_dc; - HGLRC gl_context; gint win_xpos; gint win_ypos; gint win_width; @@ -65,8 +64,6 @@ struct _ClutterStageWin32Class GType clutter_stage_win32_get_type (void) G_GNUC_CONST; -HWND clutter_win32_get_stage_window (ClutterStage *stage); - void clutter_stage_win32_map (ClutterStageWin32 *stage_win32); void clutter_stage_win32_unmap (ClutterStageWin32 *stage_win32); diff --git a/clutter/win32/clutter-win32.h b/clutter/win32/clutter-win32.h index 3f9019bce..df416e640 100644 --- a/clutter/win32/clutter-win32.h +++ b/clutter/win32/clutter-win32.h @@ -43,7 +43,8 @@ G_BEGIN_DECLS -HWND clutter_win32_get_stage_window (ClutterStage *stage); +HWND clutter_win32_get_stage_window (ClutterStage *stage); +ClutterStage *clutter_win32_get_stage_from_window (HWND hwnd); G_END_DECLS diff --git a/doc/reference/ChangeLog b/doc/reference/ChangeLog index 244977aa3..1b9ce74b7 100644 --- a/doc/reference/ChangeLog +++ b/doc/reference/ChangeLog @@ -1,3 +1,7 @@ +2008-03-30 Neil Roberts + + * clutter-sections.txt: Added clutter_win32_get_stage_from_window + 2008-03-26 Neil Roberts * clutter-sections.txt: Added a section for the Win32 specific diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index c618ff777..92065787e 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -1008,6 +1008,7 @@ clutter_x11_remove_filter
clutter-win32 Win32 Specific Support +clutter_win32_get_stage_from_window clutter_win32_get_stage_window