Compare commits
11 Commits
tmp-workbe
...
grab_walk_
Author | SHA1 | Date | |
---|---|---|---|
578f82d2ee | |||
1a419c9f4e | |||
3af3e77e67 | |||
1a00134ab0 | |||
a8f7bfa213 | |||
ccd5264344 | |||
d06fb5a92b | |||
aea5b4fbfa | |||
fa80af4455 | |||
bcab006892 | |||
fa0e0bcf32 |
@@ -108,29 +108,35 @@
|
|||||||
static void initRawInput()
|
static void initRawInput()
|
||||||
{
|
{
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
# define DEVICE_COUNT 2
|
# define DEVICE_COUNT 3
|
||||||
#else
|
#else
|
||||||
# define DEVICE_COUNT 1
|
# define DEVICE_COUNT 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAWINPUTDEVICE devices[DEVICE_COUNT];
|
RAWINPUTDEVICE devices[DEVICE_COUNT];
|
||||||
memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE));
|
memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE));
|
||||||
|
|
||||||
// Initiates WM_INPUT messages from keyboard
|
/* Initiates WM_INPUT messages from keyboard.
|
||||||
// That way GHOST can retrieve true keys
|
* That way GHOST can retrieve true keys.
|
||||||
|
*/
|
||||||
devices[0].usUsagePage = 0x01;
|
devices[0].usUsagePage = 0x01;
|
||||||
devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
|
devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
|
||||||
|
|
||||||
#ifdef WITH_INPUT_NDOF
|
/* Initiates WM_INPUT messages for mouse.
|
||||||
// multi-axis mouse (SpaceNavigator, etc.)
|
* Used to differentiate absolute and relative cursor movement.
|
||||||
|
* */
|
||||||
devices[1].usUsagePage = 0x01;
|
devices[1].usUsagePage = 0x01;
|
||||||
devices[1].usUsage = 0x08;
|
devices[1].usUsage = 0x02;
|
||||||
|
|
||||||
|
#ifdef WITH_INPUT_NDOF
|
||||||
|
/* multi - axis mouse(SpaceNavigator, etc.) */
|
||||||
|
devices[2].usUsagePage = 0x01;
|
||||||
|
devices[2].usUsage = 0x08;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE)))
|
if (!RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE))) {
|
||||||
; // yay!
|
|
||||||
else
|
|
||||||
GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
|
GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
#undef DEVICE_COUNT
|
#undef DEVICE_COUNT
|
||||||
}
|
}
|
||||||
@@ -150,6 +156,8 @@ GHOST_SystemWin32::GHOST_SystemWin32()
|
|||||||
// blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI.
|
// blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI.
|
||||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
|
||||||
|
EnableMouseInPointer(true);
|
||||||
|
|
||||||
// Check if current keyboard layout uses AltGr and save keylayout ID for
|
// Check if current keyboard layout uses AltGr and save keylayout ID for
|
||||||
// specialized handling if keys like VK_OEM_*. I.e. french keylayout
|
// specialized handling if keys like VK_OEM_*. I.e. french keylayout
|
||||||
// generates VK_OEM_8 for their exclamation key (key left of right shift)
|
// generates VK_OEM_8 for their exclamation key (key left of right shift)
|
||||||
@@ -160,6 +168,11 @@ GHOST_SystemWin32::GHOST_SystemWin32()
|
|||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
m_ndofManager = new GHOST_NDOFManagerWin32(*this);
|
m_ndofManager = new GHOST_NDOFManagerWin32(*this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
POINT pt;
|
||||||
|
::GetCursorPos(&pt);
|
||||||
|
m_lastX = pt.x;
|
||||||
|
m_lastY = pt.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_SystemWin32::~GHOST_SystemWin32()
|
GHOST_SystemWin32::~GHOST_SystemWin32()
|
||||||
@@ -461,6 +474,8 @@ GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(int32_t &x, int32_t &y) cons
|
|||||||
|
|
||||||
GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y)
|
GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
|
/* Don't use SendInput or mouse_event functions. Unlike SetCursorPos, they are received by
|
||||||
|
* WM_INPUT processing and interrupt differentiating absolute vs relative mouse input. */
|
||||||
if (!::GetActiveWindow())
|
if (!::GetActiveWindow())
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||||
@@ -878,7 +893,7 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
|
|||||||
return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td);
|
return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window, UINT genSerial)
|
||||||
{
|
{
|
||||||
GHOST_Wintab *wt = window->getWintab();
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
if (!wt) {
|
if (!wt) {
|
||||||
@@ -888,7 +903,7 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
|||||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||||
|
|
||||||
std::vector<GHOST_WintabInfoWin32> wintabInfo;
|
std::vector<GHOST_WintabInfoWin32> wintabInfo;
|
||||||
wt->getInput(wintabInfo);
|
wt->getInput(wintabInfo, genSerial);
|
||||||
|
|
||||||
/* Wintab provided coordinates are untrusted until a Wintab and Win32 button down event match.
|
/* Wintab provided coordinates are untrusted until a Wintab and Win32 button down event match.
|
||||||
* This is checked on every button down event, and revoked if there is a mismatch. This can
|
* This is checked on every button down event, and revoked if there is a mismatch. This can
|
||||||
@@ -896,9 +911,7 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
|||||||
*
|
*
|
||||||
* If Wintab was never trusted while processing this Win32 event, a fallback Ghost cursor move
|
* If Wintab was never trusted while processing this Win32 event, a fallback Ghost cursor move
|
||||||
* event is created at the position of the Win32 WT_PACKET event. */
|
* event is created at the position of the Win32 WT_PACKET event. */
|
||||||
bool mouseMoveHandled;
|
bool useWintabPos = wt->trustCoordinates();
|
||||||
bool useWintabPos;
|
|
||||||
mouseMoveHandled = useWintabPos = wt->trustCoordinates();
|
|
||||||
|
|
||||||
for (GHOST_WintabInfoWin32 &info : wintabInfo) {
|
for (GHOST_WintabInfoWin32 &info : wintabInfo) {
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
@@ -908,8 +921,30 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
|
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
|
||||||
|
|
||||||
|
if (system->m_firstProximity) {
|
||||||
|
system->m_firstProximity = false;
|
||||||
|
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
system->warpGrabAccum(window, info.x, info.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = info.x;
|
||||||
|
int y = info.y;
|
||||||
|
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
int32_t x_accum, y_accum;
|
||||||
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
|
x += x_accum;
|
||||||
|
y += y_accum;
|
||||||
|
}
|
||||||
|
|
||||||
system->pushEvent(new GHOST_EventCursor(
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
|
info.time, GHOST_kEventCursorMove, window, x, y, info.tabletData));
|
||||||
|
|
||||||
|
system->m_lastX = info.x;
|
||||||
|
system->m_lastY = info.y;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -948,14 +983,23 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
|||||||
/* Move cursor to button location, to prevent incorrect cursor position when
|
/* Move cursor to button location, to prevent incorrect cursor position when
|
||||||
* transitioning from unsynchronized Win32 to Wintab cursor control. */
|
* transitioning from unsynchronized Win32 to Wintab cursor control. */
|
||||||
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
|
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
|
||||||
|
|
||||||
|
int x = info.x;
|
||||||
|
int y = info.y;
|
||||||
|
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
int32_t x_accum, y_accum;
|
||||||
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
|
x += x_accum;
|
||||||
|
y += y_accum;
|
||||||
|
}
|
||||||
system->pushEvent(new GHOST_EventCursor(
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
|
info.time, GHOST_kEventCursorMove, window, x, y, info.tabletData));
|
||||||
|
|
||||||
window->updateMouseCapture(MousePressed);
|
window->updateMouseCapture(MousePressed);
|
||||||
system->pushEvent(
|
system->pushEvent(
|
||||||
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
||||||
|
|
||||||
mouseMoveHandled = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -996,25 +1040,18 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fallback cursor movement if Wintab position were never trusted while processing this event. */
|
|
||||||
if (!mouseMoveHandled) {
|
|
||||||
DWORD pos = GetMessagePos();
|
|
||||||
int x = GET_X_LPARAM(pos);
|
|
||||||
int y = GET_Y_LPARAM(pos);
|
|
||||||
|
|
||||||
/* TODO supply tablet data */
|
|
||||||
system->pushEvent(new GHOST_EventCursor(
|
|
||||||
system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y, GHOST_TABLET_DATA_NONE));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_SystemWin32::processPointerEvent(
|
void GHOST_SystemWin32::processPointerEvent(
|
||||||
UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled)
|
UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled)
|
||||||
{
|
{
|
||||||
|
int32_t pointerId = GET_POINTERID_WPARAM(wParam);
|
||||||
|
POINTER_INPUT_TYPE inputType;
|
||||||
|
GetPointerType(pointerId, &inputType);
|
||||||
|
|
||||||
/* Pointer events might fire when changing windows for a device which is set to use Wintab,
|
/* Pointer events might fire when changing windows for a device which is set to use Wintab,
|
||||||
* even when Wintab is left enabled but set to the bottom of Wintab overlap order. */
|
* even when Wintab is left enabled but set to the bottom of Wintab overlap order. */
|
||||||
if (!window->usingTabletAPI(GHOST_kTabletWinPointer)) {
|
if (!window->usingTabletAPI(GHOST_kTabletWinPointer) && inputType != PT_MOUSE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1022,6 +1059,13 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
std::vector<GHOST_PointerInfoWin32> pointerInfo;
|
std::vector<GHOST_PointerInfoWin32> pointerInfo;
|
||||||
|
|
||||||
if (window->getPointerInfo(pointerInfo, wParam, lParam) != GHOST_kSuccess) {
|
if (window->getPointerInfo(pointerInfo, wParam, lParam) != GHOST_kSuccess) {
|
||||||
|
if (inputType == PT_MOUSE && type == WM_POINTERUPDATE) {
|
||||||
|
GHOST_EventCursor *event = processCursorEvent(window);
|
||||||
|
if (event) {
|
||||||
|
system->pushEvent(event);
|
||||||
|
eventHandled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1030,25 +1074,43 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
|
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
|
||||||
* Only contiguous move events are coalesced. */
|
* Only contiguous move events are coalesced. */
|
||||||
for (uint32_t i = pointerInfo.size(); i-- > 0;) {
|
for (uint32_t i = pointerInfo.size(); i-- > 0;) {
|
||||||
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
|
int x = pointerInfo[i].pixelLocation.x;
|
||||||
GHOST_kEventCursorMove,
|
int y = pointerInfo[i].pixelLocation.y;
|
||||||
window,
|
|
||||||
pointerInfo[i].pixelLocation.x,
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
pointerInfo[i].pixelLocation.y,
|
int32_t x_accum, y_accum;
|
||||||
pointerInfo[i].tabletData));
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
|
x += x_accum;
|
||||||
|
y += y_accum;
|
||||||
|
}
|
||||||
|
|
||||||
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
|
pointerInfo[i].time, GHOST_kEventCursorMove, window, x, y, pointerInfo[i].tabletData));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointerInfo.size() > 0) {
|
||||||
|
GHOST_PointerInfoWin32 front = pointerInfo.front();
|
||||||
|
system->m_lastX = front.pixelLocation.x;
|
||||||
|
system->m_lastY = front.pixelLocation.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Leave event unhandled so that system cursor is moved. */
|
/* Leave event unhandled so that system cursor is moved. */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case WM_POINTERDOWN:
|
case WM_POINTERDOWN: {
|
||||||
|
int x = pointerInfo[0].pixelLocation.x;
|
||||||
|
int y = pointerInfo[0].pixelLocation.y;
|
||||||
|
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
int32_t x_accum, y_accum;
|
||||||
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
|
x += x_accum;
|
||||||
|
y += y_accum;
|
||||||
|
}
|
||||||
|
|
||||||
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
|
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
|
||||||
system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
GHOST_kEventCursorMove,
|
pointerInfo[0].time, GHOST_kEventCursorMove, window, x, y, pointerInfo[0].tabletData));
|
||||||
window,
|
|
||||||
pointerInfo[0].pixelLocation.x,
|
|
||||||
pointerInfo[0].pixelLocation.y,
|
|
||||||
pointerInfo[0].tabletData));
|
|
||||||
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
|
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
|
||||||
GHOST_kEventButtonDown,
|
GHOST_kEventButtonDown,
|
||||||
window,
|
window,
|
||||||
@@ -1060,6 +1122,7 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case WM_POINTERUP:
|
case WM_POINTERUP:
|
||||||
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
|
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
|
||||||
GHOST_kEventButtonUp,
|
GHOST_kEventButtonUp,
|
||||||
@@ -1079,20 +1142,49 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
|
|
||||||
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
|
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
|
||||||
{
|
{
|
||||||
int32_t x_screen, y_screen;
|
|
||||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||||
|
|
||||||
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
|
/* Don't use GetPointerInfo to obtain mouse position. It is identical to GetMessagePos for
|
||||||
/* While pen devices are in range, cursor movement is handled by tablet input processing. */
|
* WM_POINTERUPDATE messages, but returns outdated position for WM_POINTERLEAVE messages thus
|
||||||
return NULL;
|
* doesn't warp when it should.
|
||||||
|
* This difference only seems to occur while RAWINPUT mouse processing is enabled. */
|
||||||
|
DWORD pos = ::GetMessagePos();
|
||||||
|
int32_t x_screen = GET_X_LPARAM(pos);
|
||||||
|
int32_t y_screen = GET_Y_LPARAM(pos);
|
||||||
|
|
||||||
|
/* TODO supply tablet data */
|
||||||
|
GHOST_TabletData td = window->getTabletData();
|
||||||
|
td.Pressure = 1.0f;
|
||||||
|
|
||||||
|
if (td.Active != GHOST_kTabletModeNone) {
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (window->usingTabletAPI(GHOST_kTabletWintab) && wt && !wt->trustCoordinates()) {
|
||||||
|
/* Fallback cursor movement if Wintab position were never trusted while processing this
|
||||||
|
* event. This may happen if the tablet coordinate scaling is off, hasn't yet been
|
||||||
|
verified,
|
||||||
|
* or if the tablet is in mouse mode. */
|
||||||
|
|
||||||
|
if (system->m_firstProximity) {
|
||||||
|
system->m_firstProximity = false;
|
||||||
|
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
system->warpGrabAccum(window, x_screen, y_screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* While pen devices are in range, cursor movement is handled by tablet input processing.
|
||||||
|
*/
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
system->getCursorPosition(x_screen, y_screen);
|
int32_t x_accum = 0;
|
||||||
|
int32_t y_accum = 0;
|
||||||
|
|
||||||
if (window->getCursorGrabModeIsWarp()) {
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
int32_t x_new = x_screen;
|
int32_t x_new = x_screen;
|
||||||
int32_t y_new = y_screen;
|
int32_t y_new = y_screen;
|
||||||
int32_t x_accum, y_accum;
|
|
||||||
GHOST_Rect bounds;
|
GHOST_Rect bounds;
|
||||||
|
|
||||||
/* Fallback to window bounds. */
|
/* Fallback to window bounds. */
|
||||||
@@ -1105,30 +1197,45 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||||||
bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
|
bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
|
||||||
|
|
||||||
window->getCursorGrabAccum(x_accum, y_accum);
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
if (x_new != x_screen || y_new != y_screen) {
|
int32_t warpX = x_new - x_screen;
|
||||||
/* When wrapping we don't need to add an event because the setCursorPosition call will cause
|
int32_t warpY = y_new - y_screen;
|
||||||
* a new event after. */
|
if ((warpX || warpY) && !system->m_absoluteCursor) {
|
||||||
system->setCursorPosition(x_new, y_new); /* wrap */
|
system->setCursorPosition(x_new, y_new); /* wrap */
|
||||||
window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
|
|
||||||
|
/* We may be in an event before cursor wrap has taken effect */
|
||||||
|
if (window->m_activeWarpX >= 0 && warpX < 0 || window->m_activeWarpX <= 0 && warpX > 0) {
|
||||||
|
x_accum -= warpX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->m_activeWarpY >= 0 && warpY < 0 || window->m_activeWarpY <= 0 && warpY > 0) {
|
||||||
|
y_accum -= warpY;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->setCursorGrabAccum(x_accum, y_accum);
|
||||||
|
|
||||||
|
window->m_activeWarpX = warpX;
|
||||||
|
window->m_activeWarpY = warpY;
|
||||||
|
|
||||||
|
/* Accum not relative to new cursor position, update screen position so the event will be
|
||||||
|
* placed correctly. */
|
||||||
|
x_screen = x_new;
|
||||||
|
y_screen = y_new;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
window->m_activeWarpX = 0;
|
||||||
GHOST_kEventCursorMove,
|
window->m_activeWarpY = 0;
|
||||||
window,
|
|
||||||
x_screen + x_accum,
|
|
||||||
y_screen + y_accum,
|
|
||||||
GHOST_TABLET_DATA_NONE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
system->m_lastX = x_screen;
|
||||||
GHOST_kEventCursorMove,
|
system->m_lastY = y_screen;
|
||||||
window,
|
|
||||||
x_screen,
|
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||||
y_screen,
|
GHOST_kEventCursorMove,
|
||||||
GHOST_TABLET_DATA_NONE);
|
window,
|
||||||
}
|
x_screen + x_accum,
|
||||||
return NULL;
|
y_screen + y_accum,
|
||||||
|
td);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
|
void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
|
||||||
@@ -1454,6 +1561,18 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case RIM_TYPEMOUSE: {
|
||||||
|
/* We would like to correlate absolute/relative input to specific devices in
|
||||||
|
* WM_POINTER, but all PT_MOUSE pointers' device handle contains the same virtual
|
||||||
|
* mouse thus loose device information. */
|
||||||
|
bool now = raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE;
|
||||||
|
if (system->m_absoluteCursor ^ now) {
|
||||||
|
printf("%d\n", now);
|
||||||
|
}
|
||||||
|
system->m_absoluteCursor = raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE;
|
||||||
|
eventHandled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1606,9 +1725,39 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
if (inRange) {
|
if (inRange) {
|
||||||
/* Some devices don't emit WT_CSRCHANGE events, so update cursor info here. */
|
/* Some devices don't emit WT_CSRCHANGE events, so update cursor info here. */
|
||||||
wt->updateCursorInfo();
|
wt->updateCursorInfo();
|
||||||
|
|
||||||
|
wt->enterRange();
|
||||||
|
|
||||||
|
window->m_mousePresent = true;
|
||||||
|
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
system->m_firstProximity = true;
|
||||||
|
/* Mouse events are still generated asynchronously and may have been processed
|
||||||
|
* while Wintab was out of range, thus we may be in the middle of a cursor wrap
|
||||||
|
* event. */
|
||||||
|
window->m_activeWarpX = 0;
|
||||||
|
window->m_activeWarpY = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wt->leaveRange();
|
wt->leaveRange();
|
||||||
|
|
||||||
|
/* Check if pointer device left range while outside of the window. This is necessary
|
||||||
|
* because WM_POINTERENTER and WM_POINTERLEAVE events don't fire when a pen enters
|
||||||
|
* and leaves without hoving over the window, but the cursor is moved resulting in a
|
||||||
|
* WM_POINTERLEAVE event for the mouse. */
|
||||||
|
int32_t msgPosX;
|
||||||
|
int32_t msgPosY;
|
||||||
|
system->getCursorPosition(msgPosX, msgPosY);
|
||||||
|
|
||||||
|
GHOST_Rect bounds;
|
||||||
|
window->getClientBounds(bounds);
|
||||||
|
|
||||||
|
if (!bounds.isInside(msgPosX, msgPosY)) {
|
||||||
|
window->m_mousePresent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
@@ -1627,29 +1776,145 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WT_PACKET:
|
case WT_PACKET:
|
||||||
processWintabEvent(window);
|
processWintabEvent(window, wParam);
|
||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
break;
|
break;
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Pointer events, processed
|
// Pointer events, processed
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
case WM_POINTERUPDATE:
|
case WM_POINTERUPDATE:
|
||||||
|
if (!window->m_mousePresent) {
|
||||||
|
/* Wintab asynchronously generates mouse events, if a pen briefly enters then leaves
|
||||||
|
* outside of the window the associated mouse movements may arrive late, thus we will
|
||||||
|
* wrap the cursor, leading to an unintuitive jump. */
|
||||||
|
if (window->usingTabletAPI(GHOST_kTabletWintab) && window->getCursorGrabModeIsWarp() &&
|
||||||
|
!window->m_activeWarpX && !window->m_activeWarpY) {
|
||||||
|
int32_t x, y;
|
||||||
|
system->getCursorPosition(x, y);
|
||||||
|
|
||||||
|
GHOST_Rect bounds;
|
||||||
|
window->getClientBounds(bounds);
|
||||||
|
|
||||||
|
if (!bounds.isInside(x, y)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->m_mousePresent = true;
|
||||||
|
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->gainFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only adjust cursor/grab accum offset if not in the middle of a warp event. */
|
||||||
|
if (window->getCursorGrabModeIsWarp() && !window->m_activeWarpX &&
|
||||||
|
!window->m_activeWarpY) {
|
||||||
|
uint32_t pointerId = GET_POINTERID_WPARAM(wParam);
|
||||||
|
POINTER_INFO pointerInfo;
|
||||||
|
GetPointerInfo(pointerId, &pointerInfo);
|
||||||
|
int x = pointerInfo.ptPixelLocation.x;
|
||||||
|
int y = pointerInfo.ptPixelLocation.y;
|
||||||
|
|
||||||
|
system->warpGrabAccum(window, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processPointerEvent(msg, window, wParam, lParam, eventHandled);
|
||||||
|
break;
|
||||||
case WM_POINTERDOWN:
|
case WM_POINTERDOWN:
|
||||||
case WM_POINTERUP:
|
case WM_POINTERUP:
|
||||||
processPointerEvent(msg, window, wParam, lParam, eventHandled);
|
processPointerEvent(msg, window, wParam, lParam, eventHandled);
|
||||||
break;
|
break;
|
||||||
|
case WM_POINTERDEVICEINRANGE:
|
||||||
|
break;
|
||||||
|
case WM_POINTERDEVICEOUTOFRANGE: {
|
||||||
|
/* Check if pointer device left range while outside of the window. This is necessary
|
||||||
|
* because WM_POINTERENTER and WM_POINTERLEAVE events don't fire when a pen enters and
|
||||||
|
* leaves without hoving over the window, but the cursor is moved resulting in a
|
||||||
|
* WM_POINTERLEAVE event for the mouse. */
|
||||||
|
DWORD msgPos = ::GetMessagePos();
|
||||||
|
int msgPosX = GET_X_LPARAM(msgPos);
|
||||||
|
int msgPosY = GET_Y_LPARAM(msgPos);
|
||||||
|
|
||||||
|
GHOST_Rect bounds;
|
||||||
|
window->getClientBounds(bounds);
|
||||||
|
|
||||||
|
if (!bounds.isInside(msgPosX, msgPosY)) {
|
||||||
|
window->m_mousePresent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_POINTERENTER: {
|
||||||
|
/* XXX no pointerenter for PT_MOUSE. */
|
||||||
|
|
||||||
|
uint32_t pointerId = GET_POINTERID_WPARAM(wParam);
|
||||||
|
POINTER_INPUT_TYPE type;
|
||||||
|
if (!GetPointerType(pointerId, &type)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if mouse is not present, don't apply warp as it will be handled in WM_POINTERUPDATE */
|
||||||
|
/* XXX this is likely causing issues on leaving/entering across same process windows. */
|
||||||
|
if (window->getCursorGrabModeIsWarp() && window->m_mousePresent) {
|
||||||
|
if (type == PT_PEN && window->usingTabletAPI(GHOST_kTabletWintab)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = GET_X_LPARAM(lParam);
|
||||||
|
int y = GET_Y_LPARAM(lParam);
|
||||||
|
// XXX clienttoscreen?
|
||||||
|
|
||||||
|
system->warpGrabAccum(window, x, y);
|
||||||
|
|
||||||
|
window->m_activeWarpX = 0;
|
||||||
|
window->m_activeWarpY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case WM_POINTERLEAVE: {
|
case WM_POINTERLEAVE: {
|
||||||
uint32_t pointerId = GET_POINTERID_WPARAM(wParam);
|
uint32_t pointerId = GET_POINTERID_WPARAM(wParam);
|
||||||
POINTER_INFO pointerInfo;
|
POINTER_INPUT_TYPE type;
|
||||||
if (!GetPointerInfo(pointerId, &pointerInfo)) {
|
if (!GetPointerType(pointerId, &type)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset pointer pen info if pen device has left tracking range. */
|
/* Reset pointer pen info if pen device has left tracking range. */
|
||||||
if (pointerInfo.pointerType == PT_PEN) {
|
/* XXX Note, because touch is considered a left button down, it is never in range when it
|
||||||
|
* leaves */
|
||||||
|
if (type == PT_PEN) {
|
||||||
|
if (window->usingTabletAPI(GHOST_kTabletWintab)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
window->resetPointerPenInfo();
|
window->resetPointerPenInfo();
|
||||||
|
|
||||||
|
/* If pen is still in range, the cursor left the window via a hovering pen. */
|
||||||
|
if (IS_POINTER_INRANGE_WPARAM(wParam)) {
|
||||||
|
window->m_mousePresent = false;
|
||||||
|
}
|
||||||
|
|
||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
}
|
}
|
||||||
|
else if (type == PT_MOUSE && window->m_mousePresent) {
|
||||||
|
/* XXX this fires when a mouse is moved after having left from a pen device entering
|
||||||
|
* while outside of the window. */
|
||||||
|
window->m_mousePresent = false;
|
||||||
|
/* Check for tablet data in case mouse movement is actually a Wintab device. */
|
||||||
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
|
event = processCursorEvent(window);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->loseFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandled = true;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1690,20 +1955,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
if (!window->m_mousePresent) {
|
|
||||||
TRACKMOUSEEVENT tme = {sizeof(tme)};
|
|
||||||
tme.dwFlags = TME_LEAVE;
|
|
||||||
tme.hwndTrack = hwnd;
|
|
||||||
TrackMouseEvent(&tme);
|
|
||||||
window->m_mousePresent = true;
|
|
||||||
GHOST_Wintab *wt = window->getWintab();
|
|
||||||
if (wt) {
|
|
||||||
wt->gainFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event = processCursorEvent(window);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case WM_MOUSEWHEEL: {
|
case WM_MOUSEWHEEL: {
|
||||||
/* The WM_MOUSEWHEEL message is sent to the focus window
|
/* The WM_MOUSEWHEEL message is sent to the focus window
|
||||||
@@ -1739,17 +1990,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_MOUSELEAVE: {
|
case WM_MOUSELEAVE: {
|
||||||
window->m_mousePresent = false;
|
|
||||||
if (window->getTabletData().Active == GHOST_kTabletModeNone) {
|
|
||||||
event = processCursorEvent(window);
|
|
||||||
}
|
|
||||||
GHOST_Wintab *wt = window->getWintab();
|
|
||||||
if (wt) {
|
|
||||||
wt->loseFocus();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
// Mouse events, ignored
|
// Mouse events, ignored
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
case WM_NCMOUSEMOVE:
|
case WM_NCMOUSEMOVE:
|
||||||
@@ -1794,9 +2036,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
window);
|
window);
|
||||||
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
|
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
|
||||||
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
|
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
|
||||||
if (LOWORD(wParam) == WA_INACTIVE)
|
if (LOWORD(wParam) == WA_INACTIVE) {
|
||||||
window->lostMouseCapture();
|
window->lostMouseCapture();
|
||||||
|
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->loseFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2250,3 +2498,12 @@ int GHOST_SystemWin32::toggleConsole(int action)
|
|||||||
|
|
||||||
return m_consoleStatus;
|
return m_consoleStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GHOST_SystemWin32::warpGrabAccum(GHOST_WindowWin32 *win, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
int32_t x_accum, y_accum;
|
||||||
|
win->getCursorGrabAccum(x_accum, y_accum);
|
||||||
|
x_accum -= x - this->m_lastX;
|
||||||
|
y_accum -= y - this->m_lastY;
|
||||||
|
win->setCursorGrabAccum(x_accum, y_accum);
|
||||||
|
}
|
||||||
|
@@ -321,8 +321,9 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||||||
/**
|
/**
|
||||||
* Creates tablet events from Wintab events.
|
* Creates tablet events from Wintab events.
|
||||||
* \param window: The window receiving the event (the active window).
|
* \param window: The window receiving the event (the active window).
|
||||||
|
* \param TODO
|
||||||
*/
|
*/
|
||||||
static void processWintabEvent(GHOST_WindowWin32 *window);
|
static void processWintabEvent(GHOST_WindowWin32 *window, UINT genSerial);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates tablet events from pointer events.
|
* Creates tablet events from pointer events.
|
||||||
@@ -471,6 +472,13 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||||||
|
|
||||||
/** Wheel delta accumulator. */
|
/** Wheel delta accumulator. */
|
||||||
int m_wheelDeltaAccum;
|
int m_wheelDeltaAccum;
|
||||||
|
|
||||||
|
int32_t m_lastX;
|
||||||
|
int32_t m_lastY;
|
||||||
|
bool m_firstProximity = false;
|
||||||
|
bool m_absoluteCursor = false;
|
||||||
|
|
||||||
|
void warpGrabAccum(GHOST_WindowWin32 *win, int32_t x, int32_t y);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys &keys) const
|
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys &keys) const
|
||||||
|
@@ -1072,8 +1072,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
|
|||||||
|
|
||||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
||||||
{
|
{
|
||||||
GHOST_TSuccess err = GHOST_kSuccess;
|
|
||||||
|
|
||||||
if (mode != GHOST_kGrabDisable) {
|
if (mode != GHOST_kGrabDisable) {
|
||||||
// No need to perform grab without warp as it is always on in OS X
|
// No need to perform grab without warp as it is always on in OS X
|
||||||
if (mode != GHOST_kGrabNormal) {
|
if (mode != GHOST_kGrabNormal) {
|
||||||
@@ -1103,7 +1101,8 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
|
|||||||
setCursorGrabAccum(0, 0);
|
setCursorGrabAccum(0, 0);
|
||||||
m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
|
m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
|
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
|
||||||
|
@@ -75,6 +75,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
|||||||
m_isDialog(dialog),
|
m_isDialog(dialog),
|
||||||
m_hasMouseCaptured(false),
|
m_hasMouseCaptured(false),
|
||||||
m_hasGrabMouse(false),
|
m_hasGrabMouse(false),
|
||||||
|
m_activeWarpX(0),
|
||||||
|
m_activeWarpY(0),
|
||||||
m_nPressedButtons(0),
|
m_nPressedButtons(0),
|
||||||
m_customCursor(0),
|
m_customCursor(0),
|
||||||
m_wantAlphaBackground(alphaBackground),
|
m_wantAlphaBackground(alphaBackground),
|
||||||
@@ -192,6 +194,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
|||||||
loadWintab(GHOST_kWindowStateMinimized != state);
|
loadWintab(GHOST_kWindowStateMinimized != state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegisterPointerDeviceNotifications(m_hWnd, TRUE);
|
||||||
|
|
||||||
/* Allow the showing of a progress bar on the taskbar. */
|
/* Allow the showing of a progress bar on the taskbar. */
|
||||||
CoCreateInstance(
|
CoCreateInstance(
|
||||||
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
|
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
|
||||||
@@ -625,6 +629,7 @@ void GHOST_WindowWin32::lostMouseCapture()
|
|||||||
m_hasGrabMouse = false;
|
m_hasGrabMouse = false;
|
||||||
m_nPressedButtons = 0;
|
m_nPressedButtons = 0;
|
||||||
m_hasMouseCaptured = false;
|
m_hasMouseCaptured = false;
|
||||||
|
m_mousePresent = false; // XXX necessary?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,6 +825,8 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
|
|||||||
if (mode != GHOST_kGrabNormal) {
|
if (mode != GHOST_kGrabNormal) {
|
||||||
m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||||
setCursorGrabAccum(0, 0);
|
setCursorGrabAccum(0, 0);
|
||||||
|
m_activeWarpX = 0;
|
||||||
|
m_activeWarpY = 0;
|
||||||
|
|
||||||
if (mode == GHOST_kGrabHide)
|
if (mode == GHOST_kGrabHide)
|
||||||
setWindowCursorVisibility(false);
|
setWindowCursorVisibility(false);
|
||||||
@@ -843,6 +850,8 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
|
|||||||
/* Almost works without but important otherwise the mouse GHOST location
|
/* Almost works without but important otherwise the mouse GHOST location
|
||||||
* can be incorrect on exit. */
|
* can be incorrect on exit. */
|
||||||
setCursorGrabAccum(0, 0);
|
setCursorGrabAccum(0, 0);
|
||||||
|
m_activeWarpX = 0;
|
||||||
|
m_activeWarpY = 0;
|
||||||
m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
|
m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
|
||||||
updateMouseCapture(OperatorUngrab);
|
updateMouseCapture(OperatorUngrab);
|
||||||
}
|
}
|
||||||
@@ -872,6 +881,11 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
|||||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
||||||
uint32_t outCount = 0;
|
uint32_t outCount = 0;
|
||||||
|
|
||||||
|
POINTER_INPUT_TYPE inputType;
|
||||||
|
if (GetPointerType(pointerId, &inputType) && inputType == PT_MOUSE) {
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) {
|
if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) {
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
}
|
}
|
||||||
@@ -950,6 +964,11 @@ void GHOST_WindowWin32::resetPointerPenInfo()
|
|||||||
m_lastPointerTabletData = GHOST_TABLET_DATA_NONE;
|
m_lastPointerTabletData = GHOST_TABLET_DATA_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GHOST_WindowWin32::setPointerPenInfo()
|
||||||
|
{
|
||||||
|
m_lastPointerTabletData.Active = GHOST_kTabletModeStylus;
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_Wintab *GHOST_WindowWin32::getWintab() const
|
GHOST_Wintab *GHOST_WindowWin32::getWintab() const
|
||||||
{
|
{
|
||||||
return m_wintab;
|
return m_wintab;
|
||||||
|
@@ -269,6 +269,8 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
|||||||
*/
|
*/
|
||||||
void resetPointerPenInfo();
|
void resetPointerPenInfo();
|
||||||
|
|
||||||
|
void setPointerPenInfo();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves pointer to Wintab if Wintab is the set Tablet API.
|
* Retrieves pointer to Wintab if Wintab is the set Tablet API.
|
||||||
* \return Pointer to Wintab member.
|
* \return Pointer to Wintab member.
|
||||||
@@ -307,6 +309,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
|||||||
|
|
||||||
/** True if the mouse is either over or captured by the window. */
|
/** True if the mouse is either over or captured by the window. */
|
||||||
bool m_mousePresent;
|
bool m_mousePresent;
|
||||||
|
/** Active cursor warp in x axis. */
|
||||||
|
int32_t m_activeWarpX;
|
||||||
|
/** Active cursor warp in y axis. */
|
||||||
|
int32_t m_activeWarpY;
|
||||||
|
|
||||||
/** True if the window currently resizing. */
|
/** True if the window currently resizing. */
|
||||||
bool m_inLiveResize;
|
bool m_inLiveResize;
|
||||||
|
@@ -63,6 +63,17 @@ GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto dataGet = (GHOST_WIN32_WTDataGet)::GetProcAddress(handle.get(), "WTDataGet");
|
||||||
|
if (!dataGet) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto queuePacketsEx = (GHOST_WIN32_WTQueuePacketsEx)::GetProcAddress(handle.get(),
|
||||||
|
"WTQueuePacketsEx");
|
||||||
|
if (!queuePacketsEx) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(handle.get(), "WTQueueSizeGet");
|
auto queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(handle.get(), "WTQueueSizeGet");
|
||||||
if (!queueSizeGet) {
|
if (!queueSizeGet) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -136,6 +147,8 @@ GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
|||||||
get,
|
get,
|
||||||
set,
|
set,
|
||||||
packetsGet,
|
packetsGet,
|
||||||
|
dataGet,
|
||||||
|
queuePacketsEx,
|
||||||
enable,
|
enable,
|
||||||
overlap,
|
overlap,
|
||||||
std::move(hctx),
|
std::move(hctx),
|
||||||
@@ -180,6 +193,8 @@ GHOST_Wintab::GHOST_Wintab(HWND hwnd,
|
|||||||
GHOST_WIN32_WTGet get,
|
GHOST_WIN32_WTGet get,
|
||||||
GHOST_WIN32_WTSet set,
|
GHOST_WIN32_WTSet set,
|
||||||
GHOST_WIN32_WTPacketsGet packetsGet,
|
GHOST_WIN32_WTPacketsGet packetsGet,
|
||||||
|
GHOST_WIN32_WTDataGet dataGet,
|
||||||
|
GHOST_WIN32_WTQueuePacketsEx queuePacketsEx,
|
||||||
GHOST_WIN32_WTEnable enable,
|
GHOST_WIN32_WTEnable enable,
|
||||||
GHOST_WIN32_WTOverlap overlap,
|
GHOST_WIN32_WTOverlap overlap,
|
||||||
unique_hctx hctx,
|
unique_hctx hctx,
|
||||||
@@ -191,6 +206,8 @@ GHOST_Wintab::GHOST_Wintab(HWND hwnd,
|
|||||||
m_fpGet{get},
|
m_fpGet{get},
|
||||||
m_fpSet{set},
|
m_fpSet{set},
|
||||||
m_fpPacketsGet{packetsGet},
|
m_fpPacketsGet{packetsGet},
|
||||||
|
m_fpDataGet{dataGet},
|
||||||
|
m_fpQueuePacketsEx{queuePacketsEx},
|
||||||
m_fpEnable{enable},
|
m_fpEnable{enable},
|
||||||
m_fpOverlap{overlap},
|
m_fpOverlap{overlap},
|
||||||
m_context{std::move(hctx)},
|
m_context{std::move(hctx)},
|
||||||
@@ -244,7 +261,16 @@ void GHOST_Wintab::leaveRange()
|
|||||||
/* Set to none to indicate tablet is inactive. */
|
/* Set to none to indicate tablet is inactive. */
|
||||||
m_lastTabletData = GHOST_TABLET_DATA_NONE;
|
m_lastTabletData = GHOST_TABLET_DATA_NONE;
|
||||||
/* Clear the packet queue. */
|
/* Clear the packet queue. */
|
||||||
m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
|
// XXX proximity may return before proximity leave is processed, this would thus clear valid
|
||||||
|
// events.
|
||||||
|
// m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::enterRange()
|
||||||
|
{
|
||||||
|
/* Dummy until input arrives. */
|
||||||
|
m_lastTabletData.Active = GHOST_kTabletModeStylus;
|
||||||
|
m_firstProximity = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_Wintab::remapCoordinates()
|
void GHOST_Wintab::remapCoordinates()
|
||||||
@@ -295,10 +321,29 @@ GHOST_TabletData GHOST_Wintab::getLastTabletData()
|
|||||||
return m_lastTabletData;
|
return m_lastTabletData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
|
void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo, UINT genSerial)
|
||||||
{
|
{
|
||||||
const int numPackets = m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
|
// const int numPackets = m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
|
||||||
|
// outWintabInfo.resize(numPackets);
|
||||||
|
UINT beginSerial, unusedEndSerial;
|
||||||
|
if (!m_fpQueuePacketsEx(m_context.get(), &beginSerial, &unusedEndSerial)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int numPackets;
|
||||||
|
m_fpDataGet(m_context.get(), beginSerial, genSerial, m_pkts.size(), m_pkts.data(), &numPackets);
|
||||||
|
|
||||||
|
/* If this is the first event since a proximity event, we want to skip all events prior to the
|
||||||
|
* one which triggered the WT_PACKET event so that we don't use events from the last time the
|
||||||
|
* stylus was in range. */
|
||||||
|
if (m_firstProximity) {
|
||||||
|
m_firstProximity = false;
|
||||||
|
|
||||||
|
m_pkts[0] = m_pkts[numPackets - 1];
|
||||||
|
numPackets = 1;
|
||||||
|
}
|
||||||
|
|
||||||
outWintabInfo.resize(numPackets);
|
outWintabInfo.resize(numPackets);
|
||||||
|
|
||||||
size_t outExtent = 0;
|
size_t outExtent = 0;
|
||||||
|
|
||||||
for (int i = 0; i < numPackets; i++) {
|
for (int i = 0; i < numPackets; i++) {
|
||||||
|
@@ -46,6 +46,8 @@ typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
|
|||||||
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
|
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
|
||||||
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
|
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
|
||||||
typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
|
typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTQueuePacketsEx)(HCTX, UINT FAR *, UINT FAR *);
|
||||||
|
typedef int(API *GHOST_WIN32_WTDataGet)(HCTX, UINT, UINT, int, LPVOID, LPINT);
|
||||||
typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
|
typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
|
||||||
typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
|
typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
|
||||||
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
|
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
|
||||||
@@ -91,6 +93,8 @@ class GHOST_Wintab {
|
|||||||
*/
|
*/
|
||||||
void loseFocus();
|
void loseFocus();
|
||||||
|
|
||||||
|
void enterRange();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up when Wintab leaves tracking range.
|
* Clean up when Wintab leaves tracking range.
|
||||||
*/
|
*/
|
||||||
@@ -130,8 +134,9 @@ class GHOST_Wintab {
|
|||||||
/**
|
/**
|
||||||
* Translate Wintab packets into GHOST_WintabInfoWin32 structs.
|
* Translate Wintab packets into GHOST_WintabInfoWin32 structs.
|
||||||
* \param outWintabInfo: Storage to return resulting GHOST_WintabInfoWin32 data.
|
* \param outWintabInfo: Storage to return resulting GHOST_WintabInfoWin32 data.
|
||||||
|
* \param TODO
|
||||||
*/
|
*/
|
||||||
void getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
|
void getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo, UINT genSerial);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether Wintab coordinates should be trusted.
|
* Whether Wintab coordinates should be trusted.
|
||||||
@@ -167,6 +172,8 @@ class GHOST_Wintab {
|
|||||||
GHOST_WIN32_WTGet m_fpGet = nullptr;
|
GHOST_WIN32_WTGet m_fpGet = nullptr;
|
||||||
GHOST_WIN32_WTSet m_fpSet = nullptr;
|
GHOST_WIN32_WTSet m_fpSet = nullptr;
|
||||||
GHOST_WIN32_WTPacketsGet m_fpPacketsGet = nullptr;
|
GHOST_WIN32_WTPacketsGet m_fpPacketsGet = nullptr;
|
||||||
|
GHOST_WIN32_WTDataGet m_fpDataGet = nullptr;
|
||||||
|
GHOST_WIN32_WTQueuePacketsEx m_fpQueuePacketsEx = nullptr;
|
||||||
GHOST_WIN32_WTEnable m_fpEnable = nullptr;
|
GHOST_WIN32_WTEnable m_fpEnable = nullptr;
|
||||||
GHOST_WIN32_WTOverlap m_fpOverlap = nullptr;
|
GHOST_WIN32_WTOverlap m_fpOverlap = nullptr;
|
||||||
|
|
||||||
@@ -176,6 +183,7 @@ class GHOST_Wintab {
|
|||||||
bool m_enabled = false;
|
bool m_enabled = false;
|
||||||
/** Whether the context has focus and is at the top of overlap order. */
|
/** Whether the context has focus and is at the top of overlap order. */
|
||||||
bool m_focused = false;
|
bool m_focused = false;
|
||||||
|
bool m_firstProximity = false;
|
||||||
|
|
||||||
/** Pressed button map. */
|
/** Pressed button map. */
|
||||||
uint8_t m_buttons = 0;
|
uint8_t m_buttons = 0;
|
||||||
@@ -219,6 +227,8 @@ class GHOST_Wintab {
|
|||||||
GHOST_WIN32_WTGet get,
|
GHOST_WIN32_WTGet get,
|
||||||
GHOST_WIN32_WTSet set,
|
GHOST_WIN32_WTSet set,
|
||||||
GHOST_WIN32_WTPacketsGet packetsGet,
|
GHOST_WIN32_WTPacketsGet packetsGet,
|
||||||
|
GHOST_WIN32_WTDataGet dataGet,
|
||||||
|
GHOST_WIN32_WTQueuePacketsEx queuePacketsEx,
|
||||||
GHOST_WIN32_WTEnable enable,
|
GHOST_WIN32_WTEnable enable,
|
||||||
GHOST_WIN32_WTOverlap overlap,
|
GHOST_WIN32_WTOverlap overlap,
|
||||||
unique_hctx hctx,
|
unique_hctx hctx,
|
||||||
|
@@ -752,10 +752,14 @@ static void flyMoveCamera(bContext *C,
|
|||||||
|
|
||||||
static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
||||||
{
|
{
|
||||||
#define FLY_ROTATE_FAC 10.0f /* more is faster */
|
/* Higher is faster. */
|
||||||
#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
|
static const float fly_rotate_factor = 10.0f;
|
||||||
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
|
/* Amount to correct per step. */
|
||||||
#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
|
static const float fly_z_up_correct_factor = 0.1f;
|
||||||
|
/* Increase upright momentum each step. */
|
||||||
|
static const float fly_z_up_correct_accel = 0.05f;
|
||||||
|
/* Higher is less lag. */
|
||||||
|
static const float fly_smooth_factor = 20.0f;
|
||||||
|
|
||||||
RegionView3D *rv3d = fly->rv3d;
|
RegionView3D *rv3d = fly->rv3d;
|
||||||
|
|
||||||
@@ -875,7 +879,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
|||||||
copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
|
copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
|
||||||
mul_m3_v3(mat, upvec);
|
mul_m3_v3(mat, upvec);
|
||||||
/* Rotate about the relative up vec */
|
/* Rotate about the relative up vec */
|
||||||
axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC);
|
axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -fly_rotate_factor);
|
||||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
||||||
|
|
||||||
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
||||||
@@ -908,7 +912,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rotate about the relative up vec */
|
/* Rotate about the relative up vec */
|
||||||
axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC);
|
axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * fly_rotate_factor);
|
||||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
||||||
|
|
||||||
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
||||||
@@ -934,10 +938,10 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
|||||||
axis_angle_to_quat(tmp_quat,
|
axis_angle_to_quat(tmp_quat,
|
||||||
upvec,
|
upvec,
|
||||||
roll * time_redraw_clamped * fly->zlock_momentum *
|
roll * time_redraw_clamped * fly->zlock_momentum *
|
||||||
FLY_ZUP_CORRECT_FAC);
|
fly_z_up_correct_factor);
|
||||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
||||||
|
|
||||||
fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
|
fly->zlock_momentum += fly_z_up_correct_accel;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* don't check until the view rotates again */
|
/* don't check until the view rotates again */
|
||||||
@@ -996,7 +1000,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
|||||||
|
|
||||||
/* impose a directional lag */
|
/* impose a directional lag */
|
||||||
interp_v3_v3v3(
|
interp_v3_v3v3(
|
||||||
dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
|
dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * fly_smooth_factor))));
|
||||||
|
|
||||||
add_v3_v3(rv3d->ofs, dvec);
|
add_v3_v3(rv3d->ofs, dvec);
|
||||||
|
|
||||||
|
@@ -284,9 +284,6 @@ typedef struct WalkInfo {
|
|||||||
bool is_reversed;
|
bool is_reversed;
|
||||||
|
|
||||||
#ifdef USE_TABLET_SUPPORT
|
#ifdef USE_TABLET_SUPPORT
|
||||||
/** Check if we had a cursor event before. */
|
|
||||||
bool is_cursor_first;
|
|
||||||
|
|
||||||
/** Tablet devices (we can't relocate the cursor). */
|
/** Tablet devices (we can't relocate the cursor). */
|
||||||
bool is_cursor_absolute;
|
bool is_cursor_absolute;
|
||||||
#endif
|
#endif
|
||||||
@@ -495,7 +492,7 @@ enum {
|
|||||||
static float base_speed = -1.0f;
|
static float base_speed = -1.0f;
|
||||||
static float userdef_speed = -1.0f;
|
static float userdef_speed = -1.0f;
|
||||||
|
|
||||||
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
|
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, wmEvent *event)
|
||||||
{
|
{
|
||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
wmWindow *win = CTX_wm_window(C);
|
wmWindow *win = CTX_wm_window(C);
|
||||||
@@ -537,6 +534,8 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
|
|||||||
userdef_speed = U.walk_navigation.walk_speed;
|
userdef_speed = U.walk_navigation.walk_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walk->moffset[0] = 0;
|
||||||
|
walk->moffset[1] = 0;
|
||||||
walk->speed = 0.0f;
|
walk->speed = 0.0f;
|
||||||
walk->is_fast = false;
|
walk->is_fast = false;
|
||||||
walk->is_slow = false;
|
walk->is_slow = false;
|
||||||
@@ -573,8 +572,6 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
|
|||||||
walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
|
walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
|
||||||
|
|
||||||
#ifdef USE_TABLET_SUPPORT
|
#ifdef USE_TABLET_SUPPORT
|
||||||
walk->is_cursor_first = true;
|
|
||||||
|
|
||||||
walk->is_cursor_absolute = false;
|
walk->is_cursor_absolute = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -622,11 +619,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
|
|||||||
walk->center_mval[1] -= walk->region->winrct.ymin;
|
walk->center_mval[1] -= walk->region->winrct.ymin;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
copy_v2_v2_int(walk->prev_mval, walk->center_mval);
|
copy_v2_v2_int(walk->prev_mval, event->mval);
|
||||||
|
|
||||||
WM_cursor_warp(win,
|
|
||||||
walk->region->winrct.xmin + walk->center_mval[0],
|
|
||||||
walk->region->winrct.ymin + walk->center_mval[1]);
|
|
||||||
|
|
||||||
/* remove the mouse cursor temporarily */
|
/* remove the mouse cursor temporarily */
|
||||||
WM_cursor_modal_set(win, WM_CURSOR_NONE);
|
WM_cursor_modal_set(win, WM_CURSOR_NONE);
|
||||||
@@ -706,59 +699,13 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
|
|||||||
walk->redraw = true;
|
walk->redraw = true;
|
||||||
}
|
}
|
||||||
else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
|
else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
|
||||||
|
|
||||||
#ifdef USE_TABLET_SUPPORT
|
|
||||||
if (walk->is_cursor_first) {
|
|
||||||
/* wait until we get the 'warp' event */
|
|
||||||
if ((walk->center_mval[0] == event->mval[0]) && (walk->center_mval[1] == event->mval[1])) {
|
|
||||||
walk->is_cursor_first = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* NOTE: its possible the system isn't giving us the warp event
|
|
||||||
* ideally we shouldn't have to worry about this, see: T45361 */
|
|
||||||
wmWindow *win = CTX_wm_window(C);
|
|
||||||
WM_cursor_warp(win,
|
|
||||||
walk->region->winrct.xmin + walk->center_mval[0],
|
|
||||||
walk->region->winrct.ymin + walk->center_mval[1]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((walk->is_cursor_absolute == false) && event->tablet.is_motion_absolute) {
|
|
||||||
walk->is_cursor_absolute = true;
|
|
||||||
copy_v2_v2_int(walk->prev_mval, event->mval);
|
|
||||||
copy_v2_v2_int(walk->center_mval, event->mval);
|
|
||||||
}
|
|
||||||
#endif /* USE_TABLET_SUPPORT */
|
|
||||||
|
|
||||||
walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
|
walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
|
||||||
walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
|
walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
|
||||||
|
|
||||||
copy_v2_v2_int(walk->prev_mval, event->mval);
|
copy_v2_v2_int(walk->prev_mval, event->mval);
|
||||||
|
|
||||||
if ((walk->center_mval[0] != event->mval[0]) || (walk->center_mval[1] != event->mval[1])) {
|
if (walk->moffset[0] != 0 || walk->moffset[1] != 0) {
|
||||||
walk->redraw = true;
|
walk->redraw = true;
|
||||||
|
|
||||||
#ifdef USE_TABLET_SUPPORT
|
|
||||||
if (walk->is_cursor_absolute) {
|
|
||||||
/* pass */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (WM_event_is_last_mousemove(event)) {
|
|
||||||
wmWindow *win = CTX_wm_window(C);
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) ||
|
|
||||||
(abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
WM_cursor_warp(win,
|
|
||||||
walk->region->winrct.xmin + walk->center_mval[0],
|
|
||||||
walk->region->winrct.ymin + walk->center_mval[1]);
|
|
||||||
copy_v2_v2_int(walk->prev_mval, walk->center_mval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
@@ -1007,14 +954,16 @@ static float getVelocityZeroTime(const float gravity, const float velocity)
|
|||||||
|
|
||||||
static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
||||||
{
|
{
|
||||||
#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */
|
/* Higher is faster, relative to region size. */
|
||||||
#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* Higher is faster, radians per-pixel. */
|
static const float walk_rotate_tablet_factor = 8.8f;
|
||||||
#define WALK_TOP_LIMIT DEG2RADF(85.0f)
|
/* Higher is faster, radians per-pixel. */
|
||||||
#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
|
static const float walk_rotate_constant_factor = DEG2RAD(0.15f);
|
||||||
#define WALK_MOVE_SPEED base_speed
|
static const float walk_top_limit = DEG2RADF(85.0f);
|
||||||
#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)
|
static const float walk_bottom_limit = DEG2RADF(-80.0f);
|
||||||
#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */
|
/* Amount to correct per step. */
|
||||||
#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */
|
static const float walk_zup_correct_fac = 0.1f;
|
||||||
|
/* Increase upright momentum each step. */
|
||||||
|
static const float walk_zup_correct_accel = 0.05f;
|
||||||
|
|
||||||
RegionView3D *rv3d = walk->rv3d;
|
RegionView3D *rv3d = walk->rv3d;
|
||||||
ARegion *region = walk->region;
|
ARegion *region = walk->region;
|
||||||
@@ -1071,13 +1020,13 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
walk->time_lastdraw = time_current;
|
walk->time_lastdraw = time_current;
|
||||||
|
|
||||||
/* base speed in m/s */
|
/* base speed in m/s */
|
||||||
walk->speed = WALK_MOVE_SPEED;
|
walk->speed = base_speed;
|
||||||
|
|
||||||
if (walk->is_fast) {
|
if (walk->is_fast) {
|
||||||
walk->speed *= WALK_BOOST_FACTOR;
|
walk->speed *= walk->speed_factor;
|
||||||
}
|
}
|
||||||
else if (walk->is_slow) {
|
else if (walk->is_slow) {
|
||||||
walk->speed *= 1.0f / WALK_BOOST_FACTOR;
|
walk->speed *= 1.0f / walk->speed_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_m3_m4(mat, rv3d->viewinv);
|
copy_m3_m4(mat, rv3d->viewinv);
|
||||||
@@ -1093,16 +1042,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
y = (float)moffset[1];
|
y = (float)moffset[1];
|
||||||
|
|
||||||
/* Speed factor. */
|
/* Speed factor. */
|
||||||
#ifdef USE_TABLET_SUPPORT
|
y *= walk_rotate_constant_factor;
|
||||||
if (walk->is_cursor_absolute) {
|
|
||||||
y /= region->winy;
|
|
||||||
y *= WALK_ROTATE_TABLET_FAC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
y *= WALK_ROTATE_CONSTANT_FAC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* user adjustment factor */
|
/* user adjustment factor */
|
||||||
y *= walk->mouse_speed;
|
y *= walk->mouse_speed;
|
||||||
@@ -1111,10 +1051,10 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
/* it ranges from 90.0f to -90.0f */
|
/* it ranges from 90.0f to -90.0f */
|
||||||
angle = -asinf(rv3d->viewmat[2][2]);
|
angle = -asinf(rv3d->viewmat[2][2]);
|
||||||
|
|
||||||
if (angle > WALK_TOP_LIMIT && y > 0.0f) {
|
if (angle > walk_top_limit && y > 0.0f) {
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
}
|
}
|
||||||
else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) {
|
else if (angle < walk_bottom_limit && y < 0.0f) {
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1142,16 +1082,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
x = (float)moffset[0];
|
x = (float)moffset[0];
|
||||||
|
|
||||||
/* Speed factor. */
|
/* Speed factor. */
|
||||||
#ifdef USE_TABLET_SUPPORT
|
x *= walk_rotate_constant_factor;
|
||||||
if (walk->is_cursor_absolute) {
|
|
||||||
x /= region->winx;
|
|
||||||
x *= WALK_ROTATE_TABLET_FAC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
x *= WALK_ROTATE_CONSTANT_FAC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* user adjustment factor */
|
/* user adjustment factor */
|
||||||
x *= walk->mouse_speed;
|
x *= walk->mouse_speed;
|
||||||
@@ -1176,10 +1107,10 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
axis_angle_to_quat(tmp_quat,
|
axis_angle_to_quat(tmp_quat,
|
||||||
upvec,
|
upvec,
|
||||||
roll * time_redraw_clamped * walk->zlock_momentum *
|
roll * time_redraw_clamped * walk->zlock_momentum *
|
||||||
WALK_ZUP_CORRECT_FAC);
|
walk_zup_correct_fac);
|
||||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
||||||
|
|
||||||
walk->zlock_momentum += WALK_ZUP_CORRECT_ACCEL;
|
walk->zlock_momentum += walk_zup_correct_accel;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Lock fixed, don't need to check it ever again. */
|
/* Lock fixed, don't need to check it ever again. */
|
||||||
@@ -1279,7 +1210,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
|
|
||||||
/* the distance we would fall naturally smoothly enough that we
|
/* the distance we would fall naturally smoothly enough that we
|
||||||
* can manually drop the object without activating gravity */
|
* can manually drop the object without activating gravity */
|
||||||
fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;
|
fall_distance = time_redraw * walk->speed * walk->speed_factor;
|
||||||
|
|
||||||
if (fabsf(difference) < fall_distance) {
|
if (fabsf(difference) < fall_distance) {
|
||||||
/* slope/stairs */
|
/* slope/stairs */
|
||||||
@@ -1392,11 +1323,6 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
#undef WALK_ROTATE_TABLET_FAC
|
|
||||||
#undef WALK_TOP_LIMIT
|
|
||||||
#undef WALK_BOTTOM_LIMIT
|
|
||||||
#undef WALK_MOVE_SPEED
|
|
||||||
#undef WALK_BOOST_FACTOR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
@@ -1445,7 +1371,7 @@ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||||||
|
|
||||||
op->customdata = walk;
|
op->customdata = walk;
|
||||||
|
|
||||||
if (initWalkInfo(C, walk, op) == false) {
|
if (initWalkInfo(C, walk, op, event) == false) {
|
||||||
MEM_freeN(op->customdata);
|
MEM_freeN(op->customdata);
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
@@ -1524,7 +1450,7 @@ void VIEW3D_OT_walk(wmOperatorType *ot)
|
|||||||
ot->poll = ED_operator_region_view3d_active;
|
ot->poll = ED_operator_region_view3d_active;
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
ot->flag = OPTYPE_BLOCKING;
|
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY | OPTYPE_GRAB_CURSOR_FORCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@@ -184,6 +184,9 @@ enum {
|
|||||||
OPTYPE_LOCK_BYPASS = (1 << 9),
|
OPTYPE_LOCK_BYPASS = (1 << 9),
|
||||||
/** Special type of undo which doesn't store itself multiple times. */
|
/** Special type of undo which doesn't store itself multiple times. */
|
||||||
OPTYPE_UNDO_GROUPED = (1 << 10),
|
OPTYPE_UNDO_GROUPED = (1 << 10),
|
||||||
|
|
||||||
|
/** Force cursor warp. */
|
||||||
|
OPTYPE_GRAB_CURSOR_FORCE = (1 << 11),
|
||||||
};
|
};
|
||||||
|
|
||||||
/** For #WM_cursor_grab_enable wrap axis. */
|
/** For #WM_cursor_grab_enable wrap axis. */
|
||||||
|
@@ -271,9 +271,7 @@ void WM_cursor_grab_enable(wmWindow *win, int wrap, bool hide, int bounds[4])
|
|||||||
|
|
||||||
if ((G.debug & G_DEBUG) == 0) {
|
if ((G.debug & G_DEBUG) == 0) {
|
||||||
if (win->ghostwin) {
|
if (win->ghostwin) {
|
||||||
if (win->eventstate->tablet.is_motion_absolute == false) {
|
GHOST_SetCursorGrab(win->ghostwin, mode, mode_axis, bounds, NULL);
|
||||||
GHOST_SetCursorGrab(win->ghostwin, mode, mode_axis, bounds, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
win->grabcursor = mode;
|
win->grabcursor = mode;
|
||||||
}
|
}
|
||||||
|
@@ -1397,7 +1397,7 @@ static int wm_operator_invoke(bContext *C,
|
|||||||
int bounds[4] = {-1, -1, -1, -1};
|
int bounds[4] = {-1, -1, -1, -1};
|
||||||
int wrap = WM_CURSOR_WRAP_NONE;
|
int wrap = WM_CURSOR_WRAP_NONE;
|
||||||
|
|
||||||
if (event && (U.uiflag & USER_CONTINUOUS_MOUSE)) {
|
if (event && (U.uiflag & USER_CONTINUOUS_MOUSE || op->flag & OPTYPE_GRAB_CURSOR_FORCE)) {
|
||||||
const wmOperator *op_test = op->opm ? op->opm : op;
|
const wmOperator *op_test = op->opm ? op->opm : op;
|
||||||
const wmOperatorType *ot_test = op_test->type;
|
const wmOperatorType *ot_test = op_test->type;
|
||||||
if ((ot_test->flag & OPTYPE_GRAB_CURSOR_XY) ||
|
if ((ot_test->flag & OPTYPE_GRAB_CURSOR_XY) ||
|
||||||
|
Reference in New Issue
Block a user