[Xephyr/GL] properly route expose event on GL drawables

When an expose event happens on an host GL window paired with an
internal drawable, route that expose event to the clients listening
to the expose event on the internal drawable.
This commit is contained in:
Dodji Seketeli 2008-02-21 15:33:02 +01:00
parent 437c78ef9f
commit c14fd2a5cb
5 changed files with 130 additions and 16 deletions

View File

@ -841,6 +841,37 @@ miPointerScreenFuncRec ephyrPointerScreenFuncs =
ephyrWarpCursor ephyrWarpCursor
}; };
/**
* find if the remote window denoted by a_remote
* is paired with an internal Window within the Xephyr server.
* If the remove window is paired with an internal window, send an
* expose event to the client insterested in the internal window expose event.
*
* Pairing happens when a drawable inside Xephyr is associated with
* a GL surface in a DRI environment.
* Look at the function ProcXF86DRICreateDrawable in ephyrdriext.c to
* know a paired window is created.
*
* This is useful to make GL drawables (only windows for now) handle
* expose events and send those events to clients.
*/
static void
ephyrExposePairedWindow (int a_remote)
{
EphyrWindowPair *pair = NULL;
RegionRec reg;
ScreenPtr screen;
if (!findWindowPairFromRemote (a_remote, &pair)) {
EPHYR_LOG ("did not find a pair for this window\n");
return;
}
screen = pair->local->drawable.pScreen;
REGION_NULL (screen, &reg);
REGION_COPY (screen, &reg, &pair->local->clipList);
screen->WindowExposures (pair->local, &reg, NullRegion);
REGION_UNINIT (screen, &reg);
}
void void
ephyrPoll(void) ephyrPoll(void)
@ -861,10 +892,14 @@ ephyrPoll(void)
if (ephyrCurScreen != ev.data.mouse_motion.screen) if (ephyrCurScreen != ev.data.mouse_motion.screen)
{ {
EPHYR_LOG ("warping mouse cursor:%d\n", ephyrCurScreen) ; EPHYR_LOG ("warping mouse cursor:%d\n", ephyrCurScreen) ;
ephyrWarpCursor(screenInfo.screens[ev.data.mouse_motion.screen], if (ev.data.mouse_motion.screen >= 0)
{
ephyrWarpCursor
(screenInfo.screens[ev.data.mouse_motion.screen],
ev.data.mouse_motion.x, ev.data.mouse_motion.x,
ev.data.mouse_motion.y ); ev.data.mouse_motion.y );
} }
}
else else
{ {
EPHYR_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; EPHYR_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ;
@ -913,6 +948,16 @@ ephyrPoll(void)
KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE); KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE);
break; break;
case EPHYR_EV_EXPOSE:
/*
* We only receive expose events when the expose event have
* be generated for a drawable that is a host X window managed
* by Xephyr. Host X windows managed by Xephyr exists for instance
* when Xephyr is asked to create a GL drawable in a DRI environment.
*/
ephyrExposePairedWindow (ev.data.expose.window);
break;
default: default:
break; break;
} }

View File

@ -59,10 +59,6 @@
#define _HAVE_XALLOC_DECLS #define _HAVE_XALLOC_DECLS
#include "ephyrlog.h" #include "ephyrlog.h"
typedef struct {
WindowPtr local ;
int remote ;
} EphyrWindowPair;
typedef struct { typedef struct {
int foo; int foo;
@ -950,6 +946,26 @@ findWindowPairFromLocal (WindowPtr a_local,
return FALSE ; return FALSE ;
} }
Bool
findWindowPairFromRemote (int a_remote,
EphyrWindowPair **a_pair)
{
int i=0 ;
EPHYR_RETURN_VAL_IF_FAIL (a_pair, FALSE) ;
for (i=0; i < NUM_WINDOW_PAIRS; i++) {
if (window_pairs[i].remote == a_remote) {
*a_pair = &window_pairs[i] ;
EPHYR_LOG ("found (%p, %d)\n",
(*a_pair)->local,
(*a_pair)->remote) ;
return TRUE ;
}
}
return FALSE ;
}
static Bool static Bool
createHostPeerWindow (const WindowPtr a_win, createHostPeerWindow (const WindowPtr a_win,
int *a_peer_win) int *a_peer_win)

View File

@ -27,6 +27,16 @@
*/ */
#ifndef __EPHYRDRIEXT_H__ #ifndef __EPHYRDRIEXT_H__
#define __EPHYRDRIEXT_H__ #define __EPHYRDRIEXT_H__
typedef struct {
WindowPtr local ;
int remote ;
} EphyrWindowPair;
Bool ephyrDRIExtensionInit (ScreenPtr a_screen) ; Bool ephyrDRIExtensionInit (ScreenPtr a_screen) ;
Bool findWindowPairFromRemote (int a_remote,
EphyrWindowPair **a_pair);
#endif /*__EPHYRDRIEXT_H__*/ #endif /*__EPHYRDRIEXT_H__*/

View File

@ -839,16 +839,38 @@ hostx_load_keymap(void)
static struct EphyrHostScreen * static struct EphyrHostScreen *
host_screen_from_window (Window w) host_screen_from_window (Window w)
{ {
int index; int index = 0;
struct EphyrHostScreen *result = NULL;
#if 0
unsigned int num_children = 0;
Window root = None, parent = None, *children = NULL;
#endif
for (index = 0 ; index < HostX.n_screens ; index++) for (index = 0 ; index < HostX.n_screens ; index++)
{ {
if (HostX.screens[index].win == w) if (HostX.screens[index].win == w)
{ {
return &HostX.screens[index]; result = &HostX.screens[index];
goto out;
} }
} }
return NULL; #if 0
XQueryTree (hostx_get_display (), w, &root, &parent,
&children, &num_children);
if (parent == root || parent == None)
goto out;
result = host_screen_from_window (parent);
#endif
out:
#if 0
if (children)
{
XFree (children);
children = NULL;
}
#endif
return result;
} }
int int
@ -870,10 +892,20 @@ hostx_get_event(EphyrHostXEvent *ev)
{ {
struct EphyrHostScreen *host_screen = struct EphyrHostScreen *host_screen =
host_screen_from_window (xev.xexpose.window); host_screen_from_window (xev.xexpose.window);
if (host_screen)
{
hostx_paint_rect (host_screen->info, 0, 0, 0, 0, hostx_paint_rect (host_screen->info, 0, 0, 0, 0,
host_screen->win_width, host_screen->win_width,
host_screen->win_height); host_screen->win_height);
} }
else
{
EPHYR_LOG_ERROR ("failed to get host screen\n");
ev->type = EPHYR_EV_EXPOSE;
ev->data.expose.window = xev.xexpose.window;
return 1;
}
}
return 0; return 0;
case MotionNotify: case MotionNotify:
@ -1113,12 +1145,18 @@ hostx_create_window (int a_screen_number,
visual_info->screen), visual_info->screen),
visual_info->visual, visual_info->visual,
AllocNone) ; AllocNone) ;
winmask = CWColormap; attrs.event_mask = ButtonPressMask
|ButtonReleaseMask
|PointerMotionMask
|KeyPressMask
|KeyReleaseMask
|ExposureMask;
winmask = CWColormap|CWEventMask;
win = XCreateWindow (dpy, hostx_get_window (a_screen_number), win = XCreateWindow (dpy, hostx_get_window (a_screen_number),
a_geometry->x, a_geometry->y, a_geometry->x, a_geometry->y,
a_geometry->width, a_geometry->height, 0, a_geometry->width, a_geometry->height, 0,
visual_info->depth, InputOutput, visual_info->depth, CopyFromParent,
visual_info->visual, winmask, &attrs) ; visual_info->visual, winmask, &attrs) ;
if (win == None) { if (win == None) {
EPHYR_LOG_ERROR ("failed to create peer window\n") ; EPHYR_LOG_ERROR ("failed to create peer window\n") ;

View File

@ -47,7 +47,8 @@ typedef enum EphyrHostXEventType
EPHYR_EV_MOUSE_PRESS, EPHYR_EV_MOUSE_PRESS,
EPHYR_EV_MOUSE_RELEASE, EPHYR_EV_MOUSE_RELEASE,
EPHYR_EV_KEY_PRESS, EPHYR_EV_KEY_PRESS,
EPHYR_EV_KEY_RELEASE EPHYR_EV_KEY_RELEASE,
EPHYR_EV_EXPOSE
} }
EphyrHostXEventType; EphyrHostXEventType;
@ -87,6 +88,10 @@ struct EphyrHostXEvent
int scancode; int scancode;
} key_down; } key_down;
struct expose {
int window;
} expose;
} data; } data;
int key_state; int key_state;