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>
* 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
{
CLUTTER_NOTE (BACKEND,
"MakeCurrent window %p, context %p",
"MakeCurrent window %p (%s), context %p",
stage_win32->hwnd,
stage_win32->is_foreign_win ? "foreign" : "native",
backend_win32->gl_context);
wglMakeCurrent (stage_win32->client_dc,
backend_win32->gl_context);
@ -366,7 +367,8 @@ clutter_backend_win32_init (ClutterBackendWin32 *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? */
clutter_backend_set_double_click_time (backend, 250);

View File

@ -45,9 +45,10 @@ struct _ClutterBackendWin32
{
ClutterBackend parent_instance;
HGLRC gl_context;
HGLRC gl_context;
gboolean no_event_retrieval;
GSource *event_source;
GSource *event_source;
};
struct _ClutterBackendWin32Class

View File

@ -212,6 +212,28 @@ make_button_event (const MSG *msg, ClutterEvent *event,
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
clutter_event_prepare (GSource *source,
gint *timeout)
@ -327,34 +349,36 @@ message_translate (ClutterBackend *backend,
switch (msg->message)
{
case WM_SIZE:
{
WORD new_width = LOWORD (msg->lParam);
WORD new_height = HIWORD (msg->lParam);
guint old_width, old_height;
if (!stage_win32->is_foreign_win)
{
WORD new_width = LOWORD (msg->lParam);
WORD new_height = HIWORD (msg->lParam);
guint old_width, old_height;
clutter_actor_get_size (CLUTTER_ACTOR (stage),
&old_width, &old_height);
clutter_actor_get_size (CLUTTER_ACTOR (stage),
&old_width, &old_height);
if (new_width != old_width || new_height != old_height)
clutter_actor_set_size (CLUTTER_ACTOR (stage),
new_width, new_height);
}
if (new_width != old_width || new_height != old_height)
clutter_actor_set_size (CLUTTER_ACTOR (stage),
new_width, new_height);
}
res = FALSE;
break;
case WM_MOVE:
{
WORD new_xpos = GET_X_LPARAM (msg->lParam);
WORD new_ypos = GET_Y_LPARAM (msg->lParam);
guint old_xpos, old_ypos;
if (!stage_win32->is_foreign_win)
{
WORD new_xpos = GET_X_LPARAM (msg->lParam);
WORD new_ypos = GET_Y_LPARAM (msg->lParam);
guint old_xpos, old_ypos;
clutter_actor_get_position (CLUTTER_ACTOR (stage),
&old_xpos, &old_ypos);
clutter_actor_get_position (CLUTTER_ACTOR (stage),
&old_xpos, &old_ypos);
if (new_xpos != old_xpos || new_ypos != old_ypos)
clutter_actor_set_position (CLUTTER_ACTOR (stage),
new_xpos, new_ypos);
}
if (new_xpos != old_xpos || new_ypos != old_ypos)
clutter_actor_set_position (CLUTTER_ACTOR (stage),
new_xpos, new_ypos);
}
res = FALSE;
break;

View File

@ -206,7 +206,7 @@ clutter_stage_win32_request_coords (ClutterActor *self,
stage_win32->win_width = new_width;
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;
@ -576,7 +576,7 @@ clutter_stage_win32_unrealize (ClutterActor *actor)
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
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->backend = NULL;
stage->scroll_pos = 0;
stage->is_foreign_win = FALSE;
stage->wrapper = NULL;
@ -687,9 +688,86 @@ clutter_win32_get_stage_from_window (HWND hwnd)
extra data */
return CLUTTER_STAGE_WIN32 (GetWindowLongPtrW (hwnd, 0))->wrapper;
else
return NULL;
{
/* 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;
}
/**
* 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
clutter_stage_win32_map (ClutterStageWin32 *stage_win32)
{

View File

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

View File

@ -43,8 +43,13 @@
G_BEGIN_DECLS
HWND clutter_win32_get_stage_window (ClutterStage *stage);
ClutterStage *clutter_win32_get_stage_from_window (HWND hwnd);
HWND clutter_win32_get_stage_window (ClutterStage *stage);
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