Fix pointer warp between screens.

In certain situations (pointer entering root on new screen)
the focus would not be properly set on the new screen.

SVN revision: 47768
This commit is contained in:
Kim Woelders 2010-04-05 17:48:37 +00:00
parent 7afd6cbe38
commit 25ea64b7b0
5 changed files with 54 additions and 18 deletions

View File

@ -521,13 +521,56 @@ FocusNewDesk(void)
XUngrabKeyboard(disp, CurrentTime); XUngrabKeyboard(disp, CurrentTime);
} }
void static void
FocusCheckScreen(void) _FocusScreenSendEvent(Window xwin, int x, int y, Time t, int enter)
{ {
if (EQueryPointer(NULL, NULL, NULL, NULL, NULL)) XEvent xe;
return; /* On screen */
FocusToEWin(NULL, FOCUS_DESK_LEAVE); xe.type = (enter) ? EnterNotify : LeaveNotify;
xe.xcrossing.window = xwin;
xe.xcrossing.root = xwin;
xe.xcrossing.subwindow = 0;
xe.xcrossing.time = t;
xe.xcrossing.x = xe.xcrossing.x_root = x;
xe.xcrossing.y = xe.xcrossing.y_root = y;
xe.xcrossing.mode = NotifyNormal;
xe.xcrossing.detail = NotifyNonlinear;
xe.xcrossing.same_screen = (enter) ? True : False;
xe.xcrossing.focus = (enter) ? False : True;
xe.xcrossing.state = 0;
XSendEvent(disp, xwin, False, EnterWindowMask | LeaveWindowMask, &xe);
}
void
FocusScreen(int scr)
{
Window xwin;
Time t;
int x, y;
if (scr < 0 || scr >= ScreenCount(disp))
return;
/* IIRC warping to a different screen once did cause
* LeaveNotify's on the current root window. This does not
* happen in xorg 1.5.3 (and probably other versions).
* So, send LeaveNotify to current root and EnterNotify
* to new root. */
t = EGetTimestamp();
/* Report LeaveNotify on current root window */
xwin = WinGetXwin(VROOT);
EXQueryPointer(xwin, &x, &y, NULL, NULL);
_FocusScreenSendEvent(xwin, x, y, t, 0);
/* Do warp and report EnterNotify on new root window */
xwin = RootWindow(disp, scr);
x = DisplayWidth(disp, scr) / 2;
y = DisplayHeight(disp, scr) / 2;
EXWarpPointer(xwin, x, y);
_FocusScreenSendEvent(xwin, x, y, t, 1);
} }
static void static void

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2009 Kim Woelders * Copyright (C) 2004-2010 Kim Woelders
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to * of this software and associated documentation files (the "Software"), to
@ -49,7 +49,7 @@ void FocusHandleChange(EWin * ewin, XEvent * ev);
void FocusHandleClick(EWin * ewin, Win win); void FocusHandleClick(EWin * ewin, Win win);
void FocusNewDeskBegin(void); void FocusNewDeskBegin(void);
void FocusNewDesk(void); void FocusNewDesk(void);
void FocusCheckScreen(void); void FocusScreen(int scr);
void ClickGrabsUpdate(void); void ClickGrabsUpdate(void);

View File

@ -1266,16 +1266,7 @@ IPC_Warp(const char *params)
{ {
x = (Dpy.screen + 1) % ScreenCount(disp); x = (Dpy.screen + 1) % ScreenCount(disp);
sscanf(params, "%*s %i", &x); sscanf(params, "%*s %i", &x);
if (x >= 0 && x < ScreenCount(disp)) FocusScreen(x);
{
EXWarpPointer(RootWindow(disp, x), DisplayWidth(disp, x) / 2,
DisplayHeight(disp, x) / 2);
/* IIRC warping to a different screen once did cause
* LeaveNotify's on the current root window. This does not
* happen in xorg 1.5.3 (and probably other versions).
* So, check and focus out if left. */
FocusCheckScreen();
}
} }
else else
{ {

View File

@ -1135,7 +1135,7 @@ EXWarpPointer(Window xwin, int x, int y)
XWarpPointer(disp, None, xwin, 0, 0, 0, 0, x, y); XWarpPointer(disp, None, xwin, 0, 0, 0, 0, x, y);
} }
static Bool Bool
EXQueryPointer(Window xwin, int *px, int *py, Window * pchild, EXQueryPointer(Window xwin, int *px, int *py, Window * pchild,
unsigned int *pmask) unsigned int *pmask)
{ {

View File

@ -221,6 +221,8 @@ Pixmap EWindowGetShapePixmapInverted(Win win);
Bool EQueryPointer(Win win, int *px, int *py, Bool EQueryPointer(Win win, int *px, int *py,
Window * pchild, unsigned int *pmask); Window * pchild, unsigned int *pmask);
Bool EXQueryPointer(Window xwin, int *px, int *py,
Window * pchild, unsigned int *pmask);
unsigned int EAllocColor(Colormap cmap, unsigned int argb); unsigned int EAllocColor(Colormap cmap, unsigned int argb);