Added support for foreign windows to the Win32 backend.

* clutter/win32/clutter-stage-win32.c
	(clutter_stage_win32_request_coords): Don't resize foreign
	windows.
	(clutter_stage_win32_unrealize): Don't destroy foreign windows.
	(clutter_stage_win32_init): Added initialiser for is_foreign_win.
	(clutter_win32_get_stage_from_window): Resort to looking in the
	stage list if the window isn't the right window class so that it
	can still find stages with foreign windows.
	(clutter_win32_set_stage_foreign): New public function to set a
	foreign window for a stage.

	* clutter/win32/clutter-event-win32.c
	(clutter_win32_disable_event_retrieval): New public function to
	disable event retrieval.
	(message_translate): Don't handle WM_SIZE or WM_MOVE for foreign
	windows.

	* clutter/win32/clutter-backend-win32.h (struct
	_ClutterBackendWin32): Added a flag to disable event retrieval

	* clutter/win32/clutter-backend-win32.c
	(clutter_backend_win32_ensure_context): Update debug note to
	include whether the stage is foreign or not.
This commit is contained in:
Neil Roberts 2008-04-15 16:12:37 +00:00
parent 429f7e64ca
commit 3d1f2a0859
7 changed files with 168 additions and 29 deletions

View File

@ -1,3 +1,31 @@
2008-04-15 Neil Roberts <neil@o-hand.com>
Added support for foreign windows to the Win32 backend.
* clutter/win32/clutter-stage-win32.c
(clutter_stage_win32_request_coords): Don't resize foreign
windows.
(clutter_stage_win32_unrealize): Don't destroy foreign windows.
(clutter_stage_win32_init): Added initialiser for is_foreign_win.
(clutter_win32_get_stage_from_window): Resort to looking in the
stage list if the window isn't the right window class so that it
can still find stages with foreign windows.
(clutter_win32_set_stage_foreign): New public function to set a
foreign window for a stage.
* clutter/win32/clutter-event-win32.c
(clutter_win32_disable_event_retrieval): New public function to
disable event retrieval.
(message_translate): Don't handle WM_SIZE or WM_MOVE for foreign
windows.
* clutter/win32/clutter-backend-win32.h (struct
_ClutterBackendWin32): Added a flag to disable event retrieval
* clutter/win32/clutter-backend-win32.c
(clutter_backend_win32_ensure_context): Update debug note to
include whether the stage is foreign or not.
2008-04-15 Øyvind Kolås <pippin@o-hand.com> 2008-04-15 Øyvind Kolås <pippin@o-hand.com>
* clutter/clutter-actor.c: (clutter_actor_set_shader_param): queue a * clutter/clutter-actor.c: (clutter_actor_set_shader_param): queue a

View File

@ -269,8 +269,9 @@ clutter_backend_win32_ensure_context (ClutterBackend *backend,
else else
{ {
CLUTTER_NOTE (BACKEND, CLUTTER_NOTE (BACKEND,
"MakeCurrent window %p, context %p", "MakeCurrent window %p (%s), context %p",
stage_win32->hwnd, stage_win32->hwnd,
stage_win32->is_foreign_win ? "foreign" : "native",
backend_win32->gl_context); backend_win32->gl_context);
wglMakeCurrent (stage_win32->client_dc, wglMakeCurrent (stage_win32->client_dc,
backend_win32->gl_context); backend_win32->gl_context);
@ -367,6 +368,7 @@ clutter_backend_win32_init (ClutterBackendWin32 *backend_win32)
ClutterBackend *backend = CLUTTER_BACKEND (backend_win32); ClutterBackend *backend = CLUTTER_BACKEND (backend_win32);
backend_win32->gl_context = NULL; backend_win32->gl_context = NULL;
backend_win32->no_event_retrieval = FALSE;
/* FIXME: get from GetSystemMetric? */ /* FIXME: get from GetSystemMetric? */
clutter_backend_set_double_click_time (backend, 250); clutter_backend_set_double_click_time (backend, 250);

View File

@ -46,6 +46,7 @@ struct _ClutterBackendWin32
ClutterBackend parent_instance; ClutterBackend parent_instance;
HGLRC gl_context; HGLRC gl_context;
gboolean no_event_retrieval;
GSource *event_source; GSource *event_source;
}; };

View File

@ -212,6 +212,28 @@ make_button_event (const MSG *msg, ClutterEvent *event,
event->button.click_count = click_count; event->button.click_count = click_count;
} }
/**
* clutter_win32_disable_event_retrieval
*
* Disables retrieval of Windows messages in the main loop. Use to
* create event-less canvas.
*
* This function can only be called before calling clutter_init().
*
* Since: 0.8
*/
void
clutter_win32_disable_event_retrieval (void)
{
ClutterBackendWin32 *backend;
ClutterMainContext *clutter_context;
clutter_context = clutter_context_get_default ();
backend = CLUTTER_BACKEND_WIN32 (clutter_context->backend);
backend->no_event_retrieval = TRUE;
}
static gboolean static gboolean
clutter_event_prepare (GSource *source, clutter_event_prepare (GSource *source,
gint *timeout) gint *timeout)
@ -327,6 +349,7 @@ message_translate (ClutterBackend *backend,
switch (msg->message) switch (msg->message)
{ {
case WM_SIZE: case WM_SIZE:
if (!stage_win32->is_foreign_win)
{ {
WORD new_width = LOWORD (msg->lParam); WORD new_width = LOWORD (msg->lParam);
WORD new_height = HIWORD (msg->lParam); WORD new_height = HIWORD (msg->lParam);
@ -343,6 +366,7 @@ message_translate (ClutterBackend *backend,
break; break;
case WM_MOVE: case WM_MOVE:
if (!stage_win32->is_foreign_win)
{ {
WORD new_xpos = GET_X_LPARAM (msg->lParam); WORD new_xpos = GET_X_LPARAM (msg->lParam);
WORD new_ypos = GET_Y_LPARAM (msg->lParam); WORD new_ypos = GET_Y_LPARAM (msg->lParam);

View File

@ -206,7 +206,7 @@ clutter_stage_win32_request_coords (ClutterActor *self,
stage_win32->win_width = new_width; stage_win32->win_width = new_width;
stage_win32->win_height = new_height; stage_win32->win_height = new_height;
if (stage_win32->hwnd != NULL) if (stage_win32->hwnd != NULL && !stage_win32->is_foreign_win)
{ {
int full_xpos, full_ypos, full_width, full_height; int full_xpos, full_ypos, full_width, full_height;
@ -576,7 +576,7 @@ clutter_stage_win32_unrealize (ClutterActor *actor)
stage_win32->client_dc = NULL; stage_win32->client_dc = NULL;
} }
if (stage_win32->hwnd) if (!stage_win32->is_foreign_win && stage_win32->hwnd)
{ {
/* Drop the pointer to this stage in the window so that any /* Drop the pointer to this stage in the window so that any
further messages won't be processed. The stage might be being further messages won't be processed. The stage might be being
@ -626,6 +626,7 @@ clutter_stage_win32_init (ClutterStageWin32 *stage)
stage->win_height = 480; stage->win_height = 480;
stage->backend = NULL; stage->backend = NULL;
stage->scroll_pos = 0; stage->scroll_pos = 0;
stage->is_foreign_win = FALSE;
stage->wrapper = NULL; stage->wrapper = NULL;
@ -687,9 +688,86 @@ clutter_win32_get_stage_from_window (HWND hwnd)
extra data */ extra data */
return CLUTTER_STAGE_WIN32 (GetWindowLongPtrW (hwnd, 0))->wrapper; return CLUTTER_STAGE_WIN32 (GetWindowLongPtrW (hwnd, 0))->wrapper;
else else
{
/* Otherwise it might be a foreign window so we should check the
stage list */
ClutterMainContext *context = clutter_context_get_default ();
ClutterStageManager *stage_manager = context->stage_manager;
GSList *l;
for (l = stage_manager->stages; l; l = l->next)
{
ClutterStage *stage = l->data;
ClutterStageWindow *impl;
impl = _clutter_stage_get_window (stage);
g_assert (CLUTTER_IS_STAGE_WIN32 (impl));
if (CLUTTER_STAGE_WIN32 (impl)->hwnd == hwnd)
return stage;
}
}
return NULL; return NULL;
} }
/**
* clutter_win32_set_stage_foreign:
* @stage: a #ClutterStage
* @hwnd: an existing window handle
*
* Target the #ClutterStage to use an existing external window handle.
*
* Return value: %TRUE if foreign window is valid
*
* Since: 0.8
*/
gboolean
clutter_win32_set_stage_foreign (ClutterStage *stage,
HWND hwnd)
{
ClutterStageWin32 *stage_win32;
ClutterStageWindow *impl;
ClutterActor *actor;
RECT client_rect;
POINT window_pos;
ClutterGeometry geom;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
g_return_val_if_fail (hwnd != NULL, FALSE);
actor = CLUTTER_ACTOR (stage);
impl = _clutter_stage_get_window (stage);
stage_win32 = CLUTTER_STAGE_WIN32 (impl);
clutter_actor_unrealize (actor);
if (!GetClientRect (hwnd, &client_rect))
{
g_warning ("Unable to retrieve the new window geometry");
return FALSE;
}
window_pos.x = client_rect.left;
window_pos.y = client_rect.right;
ClientToScreen (hwnd, &window_pos);
CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)", (int) hwnd);
stage_win32->hwnd = hwnd;
stage_win32->is_foreign_win = TRUE;
geom.x = window_pos.x;
geom.y = window_pos.y;
geom.width = client_rect.right - client_rect.left;
geom.height = client_rect.bottom - client_rect.top;
clutter_actor_set_geometry (actor, &geom);
clutter_actor_realize (actor);
return TRUE;
}
void void
clutter_stage_win32_map (ClutterStageWin32 *stage_win32) clutter_stage_win32_map (ClutterStageWin32 *stage_win32)
{ {

View File

@ -52,6 +52,7 @@ struct _ClutterStageWin32
gint win_height; gint win_height;
gint scroll_pos; gint scroll_pos;
RECT fullscreen_rect; RECT fullscreen_rect;
gboolean is_foreign_win;
ClutterBackendWin32 *backend; ClutterBackendWin32 *backend;
ClutterStageState state; ClutterStageState state;

View File

@ -46,6 +46,11 @@ 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); ClutterStage *clutter_win32_get_stage_from_window (HWND hwnd);
gboolean clutter_win32_set_stage_foreign (ClutterStage *stage,
HWND hwnd);
void clutter_win32_disable_event_retrieval (void);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_WIN32_H__ */ #endif /* __CLUTTER_WIN32_H__ */