(!1654) Xnest: use XCB for event loop
Now that no X11 calls are being done via Xlib anymore, we're free to also move over event receiving, leaving Xlib pretty much unused. Also need to add a simple event queue mechanism, because we've go a screen operation (see xnestBitBlitHelper) that needs to collect up certain events for it's return value. Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
parent
4d8ed31988
commit
164dbbb064
|
@ -34,7 +34,6 @@ is" without express or implied warranty.
|
|||
#include "Args.h"
|
||||
|
||||
char *xnestDisplayName = NULL;
|
||||
Bool xnestSynchronize = FALSE;
|
||||
Bool xnestFullGeneration = FALSE;
|
||||
int xnestDefaultClass;
|
||||
Bool xnestUserDefaultClass = FALSE;
|
||||
|
@ -60,10 +59,6 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[i], "-sync")) {
|
||||
xnestSynchronize = TRUE;
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(argv[i], "-full")) {
|
||||
xnestFullGeneration = TRUE;
|
||||
return 1;
|
||||
|
@ -177,7 +172,6 @@ void
|
|||
ddxUseMsg(void)
|
||||
{
|
||||
ErrorF("-display string display name of the real server\n");
|
||||
ErrorF("-sync sinchronize with the real server\n");
|
||||
ErrorF("-full utilize full regeneration\n");
|
||||
ErrorF("-class string default visual class\n");
|
||||
ErrorF("-depth int default depth\n");
|
||||
|
|
|
@ -19,7 +19,6 @@ is" without express or implied warranty.
|
|||
#include <X11/Xdefs.h>
|
||||
|
||||
extern char *xnestDisplayName;
|
||||
extern Bool xnestSynchronize;
|
||||
extern Bool xnestFullGeneration;
|
||||
extern int xnestDefaultClass;
|
||||
extern Bool xnestUserDefaultClass;
|
||||
|
|
|
@ -74,9 +74,6 @@ xnestOpenDisplay(int argc, char *argv[])
|
|||
FatalError("Unable to open display \"%s\".\n",
|
||||
XDisplayName(xnestDisplayName));
|
||||
|
||||
if (xnestSynchronize)
|
||||
XSynchronize(xnestDisplay, TRUE);
|
||||
|
||||
xnest_upstream_setup();
|
||||
|
||||
if (xnestParentWindow != (Window) 0)
|
||||
|
|
|
@ -32,6 +32,7 @@ is" without express or implied warranty.
|
|||
#include "mi.h"
|
||||
|
||||
#include "Xnest.h"
|
||||
#include "xnest-xcb.h"
|
||||
|
||||
#include "Args.h"
|
||||
#include "Color.h"
|
||||
|
@ -65,42 +66,6 @@ SetTimeSinceLastInputEvent(void)
|
|||
lastEventTime = GetTimeInMillis();
|
||||
}
|
||||
|
||||
static Bool
|
||||
xnestExposurePredicate(Display * dpy, XEvent * event, char *args)
|
||||
{
|
||||
return event->type == Expose || event->type == ProcessedExpose;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xnestNotExposurePredicate(Display * dpy, XEvent * event, char *args)
|
||||
{
|
||||
return !xnestExposurePredicate(dpy, event, args);
|
||||
}
|
||||
|
||||
void
|
||||
xnestCollectExposures(void)
|
||||
{
|
||||
XEvent X;
|
||||
WindowPtr pWin;
|
||||
RegionRec Rgn;
|
||||
BoxRec Box;
|
||||
|
||||
while (XCheckIfEvent(xnestDisplay, &X, xnestExposurePredicate, NULL)) {
|
||||
pWin = xnestWindowPtr(X.xexpose.window);
|
||||
|
||||
if (pWin && X.xexpose.width && X.xexpose.height) {
|
||||
Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + X.xexpose.x;
|
||||
Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + X.xexpose.y;
|
||||
Box.x2 = Box.x1 + X.xexpose.width;
|
||||
Box.y2 = Box.y1 + X.xexpose.height;
|
||||
|
||||
RegionInit(&Rgn, &Box, 1);
|
||||
|
||||
miSendExposures(pWin, &Rgn, Box.x1, Box.y1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xnestQueueKeyEvent(int type, unsigned int keycode)
|
||||
{
|
||||
|
@ -108,52 +73,62 @@ xnestQueueKeyEvent(int type, unsigned int keycode)
|
|||
QueueKeyboardEvents(xnestKeyboardDevice, type, keycode);
|
||||
}
|
||||
|
||||
#define EVTYPE(tname) tname *ev = (tname*)event
|
||||
|
||||
static void
|
||||
xnest_handle_event(XEvent X)
|
||||
xnest_handle_event(xcb_generic_event_t *event)
|
||||
{
|
||||
switch (X.type) {
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
switch (event->response_type & ~0x80) {
|
||||
case KeyPress:
|
||||
{
|
||||
xnestUpdateModifierState(X.xkey.state);
|
||||
xnestQueueKeyEvent(KeyPress, X.xkey.keycode);
|
||||
EVTYPE(xcb_key_press_event_t);
|
||||
xnestUpdateModifierState(ev->state);
|
||||
xnestQueueKeyEvent(KeyPress, ev->detail);
|
||||
break;
|
||||
}
|
||||
|
||||
case KeyRelease:
|
||||
{
|
||||
xnestUpdateModifierState(X.xkey.state);
|
||||
xnestQueueKeyEvent(KeyRelease, X.xkey.keycode);
|
||||
EVTYPE(xcb_key_release_event_t);
|
||||
xnestUpdateModifierState(ev->state);
|
||||
xnestQueueKeyEvent(KeyRelease, ev->detail);
|
||||
break;
|
||||
}
|
||||
|
||||
case ButtonPress:
|
||||
{
|
||||
ValuatorMask mask;
|
||||
EVTYPE(xcb_button_press_event_t);
|
||||
valuator_mask_set_range(&mask, 0, 0, NULL);
|
||||
xnestUpdateModifierState(X.xkey.state);
|
||||
xnestUpdateModifierState(ev->state);
|
||||
lastEventTime = GetTimeInMillis();
|
||||
QueuePointerEvents(xnestPointerDevice, ButtonPress,
|
||||
X.xbutton.button, POINTER_RELATIVE, &mask);
|
||||
ev->detail, POINTER_RELATIVE, &mask);
|
||||
break;
|
||||
}
|
||||
|
||||
case ButtonRelease:
|
||||
{
|
||||
ValuatorMask mask;
|
||||
EVTYPE(xcb_button_release_event_t);
|
||||
valuator_mask_set_range(&mask, 0, 0, NULL);
|
||||
xnestUpdateModifierState(X.xkey.state);
|
||||
xnestUpdateModifierState(ev->state);
|
||||
lastEventTime = GetTimeInMillis();
|
||||
QueuePointerEvents(xnestPointerDevice, ButtonRelease,
|
||||
X.xbutton.button, POINTER_RELATIVE, &mask);
|
||||
ev->detail, POINTER_RELATIVE, &mask);
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionNotify:
|
||||
{
|
||||
EVTYPE(xcb_motion_notify_event_t);
|
||||
ValuatorMask mask;
|
||||
int valuators[2];
|
||||
valuators[0] = X.xmotion.x;
|
||||
valuators[1] = X.xmotion.y;
|
||||
valuators[0] = ev->event_x;
|
||||
valuators[1] = ev->event_y;
|
||||
valuator_mask_set_range(&mask, 0, 2, valuators);
|
||||
lastEventTime = GetTimeInMillis();
|
||||
QueuePointerEvents(xnestPointerDevice, MotionNotify,
|
||||
|
@ -163,8 +138,9 @@ xnest_handle_event(XEvent X)
|
|||
|
||||
case FocusIn:
|
||||
{
|
||||
if (X.xfocus.detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(X.xfocus.window);
|
||||
EVTYPE(xcb_focus_in_event_t);
|
||||
if (ev->detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(ev->event);
|
||||
if (pScreen)
|
||||
xnestDirectInstallColormaps(pScreen);
|
||||
}
|
||||
|
@ -173,8 +149,9 @@ xnest_handle_event(XEvent X)
|
|||
|
||||
case FocusOut:
|
||||
{
|
||||
if (X.xfocus.detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(X.xfocus.window);
|
||||
EVTYPE(xcb_focus_out_event_t);
|
||||
if (ev->detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(ev->event);
|
||||
if (pScreen)
|
||||
xnestDirectUninstallColormaps(pScreen);
|
||||
}
|
||||
|
@ -186,15 +163,16 @@ xnest_handle_event(XEvent X)
|
|||
|
||||
case EnterNotify:
|
||||
{
|
||||
if (X.xcrossing.detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(X.xcrossing.window);
|
||||
EVTYPE(xcb_enter_notify_event_t);
|
||||
if (ev->detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(ev->event);
|
||||
if (pScreen) {
|
||||
ValuatorMask mask;
|
||||
int valuators[2];
|
||||
NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x,
|
||||
X.xcrossing.y);
|
||||
valuators[0] = X.xcrossing.x;
|
||||
valuators[1] = X.xcrossing.y;
|
||||
NewCurrentScreen(inputInfo.pointer, pScreen,
|
||||
ev->event_x, ev->event_y);
|
||||
valuators[0] = ev->event_x;
|
||||
valuators[1] = ev->event_y;
|
||||
valuator_mask_set_range(&mask, 0, 2, valuators);
|
||||
lastEventTime = GetTimeInMillis();
|
||||
QueuePointerEvents(xnestPointerDevice, MotionNotify,
|
||||
|
@ -207,8 +185,9 @@ xnest_handle_event(XEvent X)
|
|||
|
||||
case LeaveNotify:
|
||||
{
|
||||
if (X.xcrossing.detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(X.xcrossing.window);
|
||||
EVTYPE(xcb_leave_notify_event_t);
|
||||
if (ev->detail != NotifyInferior) {
|
||||
ScreenPtr pScreen = xnestScreen(ev->event);
|
||||
if (pScreen) {
|
||||
xnestDirectUninstallColormaps(pScreen);
|
||||
}
|
||||
|
@ -218,8 +197,9 @@ xnest_handle_event(XEvent X)
|
|||
|
||||
case DestroyNotify:
|
||||
{
|
||||
if (xnestParentWindow != (Window) 0 &&
|
||||
X.xdestroywindow.window == xnestParentWindow)
|
||||
xcb_destroy_notify_event_t *ev = (xcb_destroy_notify_event_t*)event;
|
||||
if (xnestParentWindow &&
|
||||
ev->window == xnestParentWindow)
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
@ -230,11 +210,35 @@ xnest_handle_event(XEvent X)
|
|||
case MapNotify:
|
||||
case ReparentNotify:
|
||||
case UnmapNotify:
|
||||
case NoExpose:
|
||||
break;
|
||||
|
||||
case Expose:
|
||||
{
|
||||
EVTYPE(xcb_expose_event_t);
|
||||
WindowPtr pWin = xnestWindowPtr(ev->window);
|
||||
if (pWin && ev->width && ev->height) {
|
||||
RegionRec Rgn;
|
||||
BoxRec Box = {
|
||||
.x1 = pWin->drawable.x + wBorderWidth(pWin) + ev->x,
|
||||
.y1 = pWin->drawable.y + wBorderWidth(pWin) + ev->y,
|
||||
.x2 = Box.x1 + ev->width,
|
||||
.y2 = Box.y1 + ev->height,
|
||||
};
|
||||
RegionInit(&Rgn, &Box, 1);
|
||||
miSendExposures(pWin, &Rgn, Box.x1, Box.y1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NoExpose:
|
||||
ErrorF("xnest: received stray NoExpose\n");
|
||||
break;
|
||||
case GraphicsExpose:
|
||||
ErrorF("xnest: received stray GraphicsExpose\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorF("xnest warning: unhandled event: %d\n", X.type);
|
||||
ErrorF("xnest warning: unhandled event: %d\n", event->response_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -242,9 +246,29 @@ xnest_handle_event(XEvent X)
|
|||
void
|
||||
xnestCollectEvents(void)
|
||||
{
|
||||
XEvent X;
|
||||
|
||||
while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) {
|
||||
xnest_handle_event(X);
|
||||
/* process queued events */
|
||||
struct xnest_event_queue *tmp = NULL, *walk = NULL;
|
||||
xorg_list_for_each_entry_safe(walk, tmp, &xnestUpstreamInfo.eventQueue.entry, entry) {
|
||||
xnest_handle_event(walk->event);
|
||||
xorg_list_del(&walk->entry);
|
||||
free(walk->event);
|
||||
free(walk);
|
||||
}
|
||||
|
||||
xcb_flush(xnestUpstreamInfo.conn);
|
||||
|
||||
int err = xcb_connection_has_error(xnestUpstreamInfo.conn);
|
||||
if (err) {
|
||||
ErrorF("Xnest: upsream connection error: %d\n", err);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* fetch new events from xcb */
|
||||
xcb_generic_event_t *event = NULL;
|
||||
while ((event = xcb_poll_for_event(xnestUpstreamInfo.conn))) {
|
||||
xnest_handle_event(event);
|
||||
free(event);
|
||||
}
|
||||
|
||||
xcb_flush(xnestUpstreamInfo.conn);
|
||||
}
|
||||
|
|
|
@ -17,12 +17,9 @@ is" without express or implied warranty.
|
|||
|
||||
#include <X11/Xmd.h>
|
||||
|
||||
#define ProcessedExpose (LASTEvent + 1)
|
||||
|
||||
extern CARD32 lastEventTime;
|
||||
|
||||
void SetTimeSinceLastInputEvent(void);
|
||||
void xnestCollectExposures(void);
|
||||
void xnestCollectEvents(void);
|
||||
void xnestQueueKeyEvent(int type, unsigned int keycode);
|
||||
|
||||
|
|
|
@ -145,21 +145,13 @@ xnestGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
|||
free(reply);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xnestBitBlitPredicate(Display * dpy, XEvent * event, char *args)
|
||||
{
|
||||
return event->type == GraphicsExpose || event->type == NoExpose;
|
||||
}
|
||||
|
||||
static RegionPtr
|
||||
xnestBitBlitHelper(GCPtr pGC)
|
||||
{
|
||||
if (!pGC->graphicsExposures)
|
||||
return NullRegion;
|
||||
else {
|
||||
XEvent event;
|
||||
RegionPtr pReg, pTmpReg;
|
||||
BoxRec Box;
|
||||
Bool pending, overlap;
|
||||
|
||||
pReg = RegionCreate(NULL, 1);
|
||||
|
@ -167,24 +159,43 @@ xnestBitBlitHelper(GCPtr pGC)
|
|||
if (!pReg || !pTmpReg)
|
||||
return NullRegion;
|
||||
|
||||
xcb_flush(xnestUpstreamInfo.conn);
|
||||
|
||||
pending = TRUE;
|
||||
while (pending) {
|
||||
XIfEvent(xnestDisplay, &event, xnestBitBlitPredicate, NULL);
|
||||
|
||||
switch (event.type) {
|
||||
case NoExpose:
|
||||
xcb_generic_event_t *event = xcb_wait_for_event(xnestUpstreamInfo.conn);
|
||||
if (!event) {
|
||||
pending = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
case GraphicsExpose:
|
||||
Box.x1 = event.xgraphicsexpose.x;
|
||||
Box.y1 = event.xgraphicsexpose.y;
|
||||
Box.x2 = event.xgraphicsexpose.x + event.xgraphicsexpose.width;
|
||||
Box.y2 = event.xgraphicsexpose.y + event.xgraphicsexpose.height;
|
||||
RegionReset(pTmpReg, &Box);
|
||||
RegionAppend(pReg, pTmpReg);
|
||||
pending = event.xgraphicsexpose.count;
|
||||
break;
|
||||
switch (event->response_type & ~0x80) {
|
||||
case NoExpose:
|
||||
pending = FALSE;
|
||||
free(event);
|
||||
break;
|
||||
|
||||
case GraphicsExpose:
|
||||
{
|
||||
xcb_graphics_exposure_event_t* ev = (xcb_graphics_exposure_event_t*)event;
|
||||
BoxRec Box = {
|
||||
.x1 = ev->x,
|
||||
.y1 = ev->y,
|
||||
.x2 = ev->x + ev->width,
|
||||
.y2 = ev->y + ev->height,
|
||||
};
|
||||
RegionReset(pTmpReg, &Box);
|
||||
RegionAppend(pReg, pTmpReg);
|
||||
pending = ev->count;
|
||||
free(event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
struct xnest_event_queue *q = malloc(sizeof(struct xnest_event_queue));
|
||||
q->event = event;
|
||||
xorg_list_add(&q->entry, &xnestUpstreamInfo.eventQueue.entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ is" without express or implied warranty.
|
|||
void
|
||||
xnestBlockHandler(void *blockData, void *timeout)
|
||||
{
|
||||
xnestCollectExposures();
|
||||
XFlush(xnestDisplay);
|
||||
xnestCollectEvents();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -37,6 +37,8 @@ void xnest_upstream_setup(void) {
|
|||
for (int i = 0; i < xnestUpstreamInfo.screenId; ++i)
|
||||
xcb_screen_next (&iter);
|
||||
xnestUpstreamInfo.screenInfo = iter.data;
|
||||
|
||||
xorg_list_init(&xnestUpstreamInfo.eventQueue.entry);
|
||||
}
|
||||
|
||||
/* retrieve upstream GC XID for our xserver GC */
|
||||
|
|
|
@ -7,11 +7,19 @@
|
|||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "include/list.h"
|
||||
|
||||
struct xnest_event_queue {
|
||||
struct xorg_list entry;
|
||||
xcb_generic_event_t *event;
|
||||
};
|
||||
|
||||
struct xnest_upstream_info {
|
||||
xcb_connection_t *conn;
|
||||
uint32_t screenId;
|
||||
const xcb_screen_t *screenInfo;
|
||||
const xcb_setup_t *setup;
|
||||
struct xnest_event_queue eventQueue;
|
||||
};
|
||||
|
||||
extern struct xnest_upstream_info xnestUpstreamInfo;
|
||||
|
|
Loading…
Reference in New Issue