Xnest: use XCB for event loop
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
parent
4fc95145ab
commit
540043413b
|
|
@ -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
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@ is" without express or implied warranty.
|
|||
void
|
||||
xnestBlockHandler(void *blockData, void *timeout)
|
||||
{
|
||||
xnestCollectExposures();
|
||||
XFlush(xnestDisplay);
|
||||
xnestCollectEvents();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue