Xnest: use XCB for event loop

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
Enrico Weigelt, metux IT consult 2024-08-20 17:23:21 +02:00
parent 4fc95145ab
commit 540043413b
9 changed files with 135 additions and 104 deletions

View File

@ -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");

View File

@ -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;

View File

@ -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)

View File

@ -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
xnestHandleEvent(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 @@ xnestHandleEvent(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 @@ xnestHandleEvent(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 @@ xnestHandleEvent(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 @@ xnestHandleEvent(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 @@ xnestHandleEvent(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 @@ xnestHandleEvent(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 @@ xnestHandleEvent(XEvent X)
void
xnestCollectEvents(void)
{
XEvent X;
while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) {
xnestHandleEvent(X);
/* process queued events */
xnestEventQueue *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);
}

View File

@ -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);

View File

@ -140,21 +140,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);
@ -162,24 +154,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:
{
xnestEventQueue *q = malloc(sizeof(xnestEventQueue));
q->event = event;
xorg_list_add(&q->entry, &xnestUpstreamInfo.eventQueue.entry);
}
}
}

View File

@ -34,8 +34,7 @@ is" without express or implied warranty.
void
xnestBlockHandler(void *blockData, void *timeout)
{
xnestCollectExposures();
XFlush(xnestDisplay);
xnestCollectEvents();
}
void

View File

@ -36,6 +36,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 */

View File

@ -7,11 +7,19 @@
#include <xcb/xcb.h>
#include "include/list.h"
typedef struct {
struct xorg_list entry;
xcb_generic_event_t *event;
} xnestEventQueue;
typedef struct {
xcb_connection_t *conn;
uint32_t screenId;
const xcb_screen_t *screenInfo;
const xcb_setup_t *setup;
xnestEventQueue eventQueue;
} xnestUpstreamInfoRec;
extern xnestUpstreamInfoRec xnestUpstreamInfo;