From da314f51bfab03252a7c530eeb3bbd5585327a25 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 19 Jun 2010 10:35:01 +0000 Subject: fixed tablet mouse spasm bug and refactored event handling --- intern/ghost/intern/GHOST_SystemCocoa.h | 20 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 397 +++++++++++++++---------------- 2 files changed, 215 insertions(+), 202 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index b97c36f04a8..d05e19ba286 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -251,13 +251,27 @@ protected: virtual GHOST_TSuccess init(); /** - * Handles a tablet event. + * Handles a tablet pen event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @param eventType The type of the event. It needs to be passed separately as it can be either directly in the event type, or as a subtype if combined with a mouse button event * @return Indication whether the event was handled. */ - GHOST_TSuccess handleTabletEvent(void *eventPtr, short eventType); + GHOST_TSuccess handleTabletEvent(void *eventPtr); + /** + * Handles a tablet proximity event. Sets pen or mouse ID for later events. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleTabletProximity(void *eventPtr); + + /** Tablet Mouse and Pen IDs, used to correlate events with the tool that caused them. */ + int m_tablet_mouse_id; + int m_tablet_pen_id; + + static const int TOOL_ID_NONE = -1; + + GHOST_TTabletMode m_tablet_pen_mode; + /** * Handles a mouse event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 2cec24714be..3edd1bd0b94 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -31,6 +31,7 @@ /*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/ #include +//#include #include #include @@ -553,6 +554,9 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() m_isGestureInProgress = false; m_cursorDelta_x=0; m_cursorDelta_y=0; + m_tablet_mouse_id = TOOL_ID_NONE; + m_tablet_pen_id = TOOL_ID_NONE; + m_tablet_pen_mode = GHOST_kTabletModeNone; m_outsideLoopEventProcessed = false; m_needDelayedApplicationBecomeActiveEventProcessing = false; m_displayManager = new GHOST_DisplayManagerCocoa (); @@ -575,10 +579,9 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl( mib, 2, rstring, &len, NULL, 0 ); //Hack on MacBook revision, as multitouch avail. function missing - if (strstr(rstring,"MacBookAir") || - (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))) - m_hasMultiTouchTrackpad = true; - else m_hasMultiTouchTrackpad = false; + m_hasMultiTouchTrackpad = + (strstr(rstring,"MacBookAir") || + (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))); free( rstring ); rstring = NULL; @@ -593,7 +596,6 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa() GHOST_TSuccess GHOST_SystemCocoa::init() { - GHOST_TSuccess success = GHOST_System::init(); if (success) { //ProcessSerialNumber psn; @@ -879,104 +881,116 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) { bool anyProcessed = false; NSEvent *event; - - // SetMouseCoalescingEnabled(false, NULL); + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + //TODO : implement timer ?? - /*do { - GHOST_TimerManager* timerMgr = getTimerManager(); + do { + event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if (event==nil) + break; - if (waitForEvent) { - GHOST_TUns64 next = timerMgr->nextFireTime(); - double timeOut; - - if (next == GHOST_kFireTimeNever) { - timeOut = kEventDurationForever; - } else { - timeOut = (double)(next - getMilliSeconds())/1000.0; - if (timeOut < 0.0) - timeOut = 0.0; - } - - ::ReceiveNextEvent(0, NULL, timeOut, false, &event); - } - - if (timerMgr->fireTimers(getMilliSeconds())) { - anyProcessed = true; - }*/ + anyProcessed = true; - do { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (event==nil) { - [pool drain]; + switch ([event type]) { + case NSKeyDown: + case NSKeyUp: + case NSFlagsChanged: + handleKeyEvent(event); + // resend to ensure Mac-wide events are handled + [NSApp sendEvent:event]; break; - } - - anyProcessed = true; - - switch ([event type]) { - case NSKeyDown: - case NSKeyUp: - case NSFlagsChanged: - handleKeyEvent(event); - - /* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */ - /* if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) { - [NSApp sendEvent:event]; - }*/ - break; - - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSScrollWheel: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - case NSEventTypeMagnify: - case NSEventTypeRotate: - case NSEventTypeBeginGesture: - case NSEventTypeEndGesture: - handleMouseEvent(event); - break; - - case NSTabletPoint: - case NSTabletProximity: - handleTabletEvent(event,[event type]); - break; - - /* Trackpad features, fired only from OS X 10.5.2 - case NSEventTypeGesture: - case NSEventTypeSwipe: - break; */ - - /*Unused events - NSMouseEntered = 8, - NSMouseExited = 9, - NSAppKitDefined = 13, - NSSystemDefined = 14, - NSApplicationDefined = 15, - NSPeriodic = 16, - NSCursorUpdate = 17,*/ - - default: - break; - } - //Resend event to NSApp to ensure Mac wide events are handled - [NSApp sendEvent:event]; - [pool drain]; - } while (event!= nil); - //} while (waitForEvent && !anyProcessed); Needed only for timer implementation + + case NSLeftMouseDown: + case NSLeftMouseUp: + case NSLeftMouseDragged: + + case NSRightMouseDown: + case NSRightMouseUp: + case NSRightMouseDragged: + + case NSOtherMouseDown: + case NSOtherMouseUp: + case NSOtherMouseDragged: + + case NSMouseMoved: + switch ([event subtype]) + { + case NSMouseEventSubtype: + handleMouseEvent(event); + break; + case NSTabletPointEventSubtype: + handleTabletEvent(event); + break; + case NSTabletProximityEventSubtype: + // I think only LMB down/up sends this + handleTabletProximity(event); + break; + + // Mac OS 10.6 introduces a Touch subtype + // that we ignore for now. + } + break; + + case NSScrollWheel: + handleMouseEvent(event); + break; + + case NSTabletProximity: + handleTabletProximity(event); + break; + + case NSTabletPoint: + if ([event deviceID] == m_tablet_pen_id) + handleTabletEvent(event); + else { + // Treat tablet mouse like any other mouse. + // TODO: teach Windows and Linux the same trick + + // It continues to send events even when still, to mimic the pen's + // ability to vary pressure without moving. Since the mouse is + // unable to vary its pressure, filter them out as noise! + + bool didMove = [event deltaX] != 0 and [event deltaY] != 0; + if (didMove) + handleMouseEvent(event); + // NSLeftMouseDown gets sent for the initial point, so this is safe. + } + break; + + case NSEventTypeMagnify: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: + handleMouseEvent(event); + // break out into handleGestureEvent? + break; + + /* Trackpad features, fired only from OS X 10.5.2 + case NSEventTypeGesture: + case NSEventTypeSwipe: + break; */ + + default: + break; + /* Unused events: + NSMouseEntered = 8, + NSMouseExited = 9, + NSAppKitDefined = 13, + NSSystemDefined = 14, + NSApplicationDefined = 15, + NSPeriodic = 16, + NSCursorUpdate = 17,*/ + } + } while (event != nil); + + [pool drain]; - if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); + if (m_needDelayedApplicationBecomeActiveEventProcessing) + handleApplicationBecomeActiveEvent(); if (m_outsideLoopEventProcessed) { m_outsideLoopEventProcessed = false; @@ -986,6 +1000,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) return anyProcessed; } + //Note: called from NSApplication delegate GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() { @@ -1360,57 +1375,81 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) else return NO; } -GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType) +GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; - GHOST_IWindow* window; - - window = m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) + m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + if (!window) { //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData(); - - switch (eventType) { - case NSTabletPoint: - ct.Pressure = [event pressure]; - ct.Xtilt = [event tilt].x; - ct.Ytilt = [event tilt].y; + GHOST_TabletData& ct = window->GetCocoaTabletData(); + + GHOST_TTabletMode active_tool; + int* tool_id_ptr; + + switch ([event pointingDeviceType]) + { + case NSPenPointingDevice: + active_tool = GHOST_kTabletModeStylus; + tool_id_ptr = &m_tablet_pen_id; break; - - case NSTabletProximity: - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; - if ([event isEnteringProximity]) - { - //pointer is entering tablet area proximity - switch ([event pointingDeviceType]) { - case NSPenPointingDevice: - ct.Active = GHOST_kTabletModeStylus; - break; - case NSEraserPointingDevice: - ct.Active = GHOST_kTabletModeEraser; - break; - case NSCursorPointingDevice: - case NSUnknownPointingDevice: - default: - ct.Active = GHOST_kTabletModeNone; - break; - } - } else { - // pointer is leaving - return to mouse - ct.Active = GHOST_kTabletModeNone; - } + case NSEraserPointingDevice: + active_tool = GHOST_kTabletModeEraser; + tool_id_ptr = &m_tablet_pen_id; break; - - default: - GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received"); - return GHOST_kFailure; + case NSCursorPointingDevice: + active_tool = GHOST_kTabletModeNone; + tool_id_ptr = &m_tablet_mouse_id; break; + default: + return GHOST_kFailure; // fail on unknown device + } + + if ([event isEnteringProximity]) { + *tool_id_ptr = [event deviceID]; + + ct.Active = active_tool; + ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0; + ct.Xtilt = 0; + ct.Ytilt = 0; + + // this is a good place to remember the tool's capabilities + // (later though, after tablet mouse is fixed and coalescing is in place) + } + else { + *tool_id_ptr = TOOL_ID_NONE; + + ct.Active = GHOST_kTabletModeNone; + ct.Pressure = 0; + ct.Xtilt = 0; + ct.Ytilt = 0; + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) +{ + NSEvent *event = (NSEvent *)eventPtr; + GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) + m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + + if (!window) { + //printf("\nW failure for event 0x%x",[event type]); + return GHOST_kFailure; } + + GHOST_TabletData& ct = window->GetCocoaTabletData(); + + ct.Pressure = [event pressure]; + NSPoint tilt = [event tilt]; + ct.Xtilt = tilt.x; + ct.Ytilt = tilt.y; + return GHOST_kSuccess; } @@ -1418,9 +1457,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; - GHOST_Window* window; - - window = (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + GHOST_Window* window = + (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + if (!window) { //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; @@ -1432,54 +1471,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSRightMouseDown: case NSOtherMouseDown: pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); - //Handle tablet events combined with mouse events - switch ([event subtype]) { - case NX_SUBTYPE_TABLET_POINT: - handleTabletEvent(eventPtr, NSTabletPoint); - break; - case NX_SUBTYPE_TABLET_PROXIMITY: - handleTabletEvent(eventPtr, NSTabletProximity); - break; - default: - //No tablet event included : do nothing - break; - } break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); - //Handle tablet events combined with mouse events - switch ([event subtype]) { - case NX_SUBTYPE_TABLET_POINT: - handleTabletEvent(eventPtr, NSTabletPoint); - break; - case NX_SUBTYPE_TABLET_PROXIMITY: - handleTabletEvent(eventPtr, NSTabletProximity); - break; - default: - //No tablet event included : do nothing - break; - } break; - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - //Handle tablet events combined with mouse events - switch ([event subtype]) { - case NX_SUBTYPE_TABLET_POINT: - handleTabletEvent(eventPtr, NSTabletPoint); - break; - case NX_SUBTYPE_TABLET_PROXIMITY: - handleTabletEvent(eventPtr, NSTabletProximity); - break; - default: - //No tablet event included : do nothing - break; - } - case NSMouseMoved: switch (window->getCursorGrabMode()) { case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move @@ -1501,6 +1500,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; + GHOST_TInt32 event_dx = [event deltaX]; + GHOST_TInt32 event_dy = -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ... GHOST_TInt32 x_accum, y_accum, x_cur, y_cur; GHOST_Rect bounds, windowBounds, correctedBounds; @@ -1508,7 +1509,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); - //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates + //Switch back to Cocoa coordinates orientation (y=0 at bottom,the same as blender internal btw!), and to client coordinates window->getClientBounds(windowBounds); window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); @@ -1517,14 +1518,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); - x_accum += [event deltaX]-m_cursorDelta_x; - y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ... + x_accum += event_dx - m_cursorDelta_x; + y_accum += event_dy - m_cursorDelta_y; window->setCursorGrabAccum(x_accum, y_accum); //Warp mouse cursor if needed - x_mouse += [event deltaX]-m_cursorDelta_x; - y_mouse += -[event deltaY]-m_cursorDelta_y; + x_mouse += event_dx - m_cursorDelta_x; + y_mouse += event_dy - m_cursorDelta_y; correctedBounds.wrapPoint(x_mouse, y_mouse, 2); //Compensate for mouse moved event taking cursor position set into account @@ -1555,16 +1556,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSScrollWheel: { /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ - if (!m_hasMultiTouchTrackpad || !m_isGestureInProgress) { - GHOST_TInt32 delta; - - double deltaF = [event deltaY]; - if (deltaF == 0.0) break; //discard trackpad delta=0 events - - delta = deltaF > 0.0 ? 1 : -1; - pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); - } - else { + if (m_hasMultiTouchTrackpad and m_isGestureInProgress) { NSPoint mousePos = [event locationInWindow]; double dx = [event deltaX]; double dy = -[event deltaY]; @@ -1584,22 +1576,29 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy)); } + else { + GHOST_TInt32 delta; + + double deltaF = [event deltaY]; + if (deltaF == 0.0) break; //discard trackpad delta=0 events + + delta = deltaF > 0.0 ? 1 : -1; + pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); + } } break; case NSEventTypeMagnify: { NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, - [event magnification]*250.0 + 0.1, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0)); } break; case NSEventTypeRotate: { NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, - -[event rotation] * 5.0, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0)); } case NSEventTypeBeginGesture: m_isGestureInProgress = true; -- cgit v1.2.3 From 185c77989e2692c13b65cea0ca8c58c4dcb51a2e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 25 Jun 2010 00:09:50 +0000 Subject: hint for mouse/pen input fidelity --- intern/ghost/GHOST_ISystem.h | 10 +++++++++- intern/ghost/intern/GHOST_System.cpp | 7 ++++++- intern/ghost/intern/GHOST_System.h | 8 ++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 8d80c74e140..1760fe30b7f 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -353,7 +353,15 @@ public: */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; - + /** Fidelity of mouse and pen input (this definition will probably live somewhere else)*/ + typedef enum { LO_FI, NORMAL_FI, HI_FI } InputFidelity; + + /** + * Requests input at a certain fidelity. Certain tools want very smooth input, others don't care. + * @param hint Desired fidelity of mouse and pen events. + */ + virtual void setInputFidelity(InputFidelity hint) = 0; + /*************************************************************************************** ** Access to clipboard. ***************************************************************************************/ diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index c89534e01c5..3cd3528eeb6 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -48,7 +48,7 @@ GHOST_System::GHOST_System() -: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0) +: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0), m_input_fidelity_hint(NORMAL_FI) { } @@ -271,6 +271,11 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown return success; } +void GHOST_System::setInputFidelity(InputFidelity hint) +{ + m_input_fidelity_hint = hint; +} + GHOST_TSuccess GHOST_System::init() { m_timerManager = new GHOST_TimerManager (); diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index d6c6a356323..6f570b33079 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -281,6 +281,12 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const = 0; + + /** + * Requests input at a certain fidelity. Certain tools want very smooth input, others don't care. + * @param hint Desired fidelity of mouse and pen events. + */ + void setInputFidelity(InputFidelity hint); /** * Returns the selection buffer @@ -354,6 +360,8 @@ protected: /** Settings of the display before the display went fullscreen. */ GHOST_DisplaySetting m_preFullScreenSetting; + + InputFidelity m_input_fidelity_hint; }; inline GHOST_TimerManager* GHOST_System::getTimerManager() const -- cgit v1.2.3 From d5cdfb18f68bd86cdb060c54b7af57f46e67c4aa Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 26 Jun 2010 01:34:49 +0000 Subject: removed unused #include --- intern/ghost/GHOST_Rect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index e3d056dd467..c72b918d63e 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -228,7 +228,7 @@ inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y) if (y < m_t) m_t = y; if (y > m_b) m_b = y; } -#include + inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs) { GHOST_TInt32 w= getWidth(); -- cgit v1.2.3 From 905fcc7b74f9d38a5449023d372b3d8fe34ee588 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 3 Jul 2010 03:53:06 +0000 Subject: guarding printf calls as MinGW (gcc 4.5) insists --- intern/ghost/intern/GHOST_DropTargetWin32.cpp | 2 ++ intern/ghost/intern/GHOST_WindowWin32.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 6470b406492..432a4f93b4d 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -377,7 +377,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out) out = (char*)::malloc(size); if (!out) { +#ifdef GHOST_DEBUG ::printf("\nmalloc failed!!!"); +#endif return 0; } diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index bbfa84dbae0..945e4c16a39 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -659,7 +659,9 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } else { +#ifdef GHOST_DEBUG printf("Failed to get a context....\n"); +#endif success = GHOST_kFailure; } } @@ -694,7 +696,9 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } else { +#ifdef GHOST_DEBUG printf("Failed to get a context....\n"); +#endif success = GHOST_kFailure; } @@ -1160,5 +1164,3 @@ static int EnumPixelFormats(HDC hdc) { } return iPixelFormat; } - - -- cgit v1.2.3 From 09f6604241982dfbd852ff3e38ce7ccdf24b43ed Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 3 Jul 2010 06:58:29 +0000 Subject: preparing for NDOF overhaul --- intern/ghost/GHOST_Types.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index f7d0425aec8..4ec8e22a960 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -444,16 +444,24 @@ typedef struct { GHOST_TUns64 delta; } GHOST_TEventNDOFData; +typedef struct { + /** N-degree of freedom device data v3 [GSoC 2010]*/ + + // Fairly close to raw device data. + // Each component normally ranges from -1 to +1, but can exceed that. + // rot axis = (rx,ry,rz).normalized + // rot amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] + + float tx, ty, tz; /** -x left, +y forward, -z up */ + float rx, ry, rz; + GHOST_TInt16 buttons; +} GHOST_TEventNDOFData_3; + +// [mce] consider scrapping these, in favor of built-in SpaceNav handling. typedef int (*GHOST_NDOFLibraryInit_fp)(); typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData); -// original patch windows callback. In mac os X version the callback is internal to the plug-in and post an event to main thead. -// not necessary faster, but better integration with other events. - -//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam); -//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas); - typedef struct { /** The key code. */ GHOST_TKey key; -- cgit v1.2.3 From 6365cb3fa8aabaaa1b8b881c3dc218c8e658f009 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 3 Jul 2010 07:03:21 +0000 Subject: much-improved tablet handling; hi-fi input for mouse/pen --- intern/ghost/intern/GHOST_SystemCocoa.h | 3 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 127 +++++++++++++++++++++++++------ 2 files changed, 104 insertions(+), 26 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index d05e19ba286..0949dca5acc 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -270,6 +270,7 @@ protected: static const int TOOL_ID_NONE = -1; + /** Which end of the pen is active: tip or eraser? */ GHOST_TTabletMode m_tablet_pen_mode; /** @@ -292,7 +293,7 @@ protected: * @param y The y-coordinate of the cursor. * @return Indication of success. */ - GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setMouseCursorPosition(float x, float y); /** Start time at initialization. */ GHOST_TUns64 m_start_time; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 3edd1bd0b94..91da1fb2d4b 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1,4 +1,4 @@ -/** +/** * $Id$ * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -23,6 +23,7 @@ * * Contributor(s): Maarten Gribnau 05/2001 * Damien Plisson 09/2009 + * Mike Erwin 06/2010 * * ***** END GPL LICENSE BLOCK ***** */ @@ -587,6 +588,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() rstring = NULL; m_ignoreWindowSizedMessages = false; + + m_input_fidelity_hint = HI_FI; // just for testing... } GHOST_SystemCocoa::~GHOST_SystemCocoa() @@ -825,9 +828,9 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 return GHOST_kSuccess; } -GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) { - float xf=(float)x, yf=(float)y; +// float xf=(float)x, yf=(float)y; GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow(); if (!window) return GHOST_kFailure; @@ -897,6 +900,9 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) switch ([event type]) { case NSKeyDown: + if ([event isARepeat]) + break; + // else fall through case NSKeyUp: case NSFlagsChanged: handleKeyEvent(event); @@ -907,15 +913,12 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) case NSLeftMouseDown: case NSLeftMouseUp: case NSLeftMouseDragged: - case NSRightMouseDown: case NSRightMouseUp: case NSRightMouseDragged: - case NSOtherMouseDown: case NSOtherMouseUp: case NSOtherMouseDragged: - case NSMouseMoved: switch ([event subtype]) { @@ -923,11 +926,15 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) handleMouseEvent(event); break; case NSTabletPointEventSubtype: - handleTabletEvent(event); + if ([event deviceID] == m_tablet_mouse_id) + handleMouseEvent(event); + else + handleTabletEvent(event); break; case NSTabletProximityEventSubtype: - // I think only LMB down/up sends this - handleTabletProximity(event); + // I think only LMB down/up sends this. + // Always preceded by a real NSTabletProximity event, so it's redundant. + // handleTabletProximity(event); break; // Mac OS 10.6 introduces a Touch subtype @@ -957,7 +964,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) bool didMove = [event deltaX] != 0 and [event deltaY] != 0; if (didMove) handleMouseEvent(event); - // NSLeftMouseDown gets sent for the initial point, so this is safe. + // LMB Down gets sent for the initial point (and LMB Up for the final), so this is safe. } break; @@ -1377,12 +1384,13 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) { + printf("tablet prox: "); NSEvent *event = (NSEvent *)eventPtr; GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); if (!window) { - //printf("\nW failure for event 0x%x",[event type]); + printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } @@ -1394,22 +1402,27 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) switch ([event pointingDeviceType]) { case NSPenPointingDevice: + printf("pen "); active_tool = GHOST_kTabletModeStylus; tool_id_ptr = &m_tablet_pen_id; break; case NSEraserPointingDevice: + printf("eraser "); active_tool = GHOST_kTabletModeEraser; tool_id_ptr = &m_tablet_pen_id; break; case NSCursorPointingDevice: + printf("cursor "); active_tool = GHOST_kTabletModeNone; tool_id_ptr = &m_tablet_mouse_id; break; default: + printf(" unknown device %d\n", [event pointingDeviceType]); return GHOST_kFailure; // fail on unknown device } if ([event isEnteringProximity]) { + printf("entering\n"); *tool_id_ptr = [event deviceID]; ct.Active = active_tool; @@ -1418,9 +1431,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) ct.Ytilt = 0; // this is a good place to remember the tool's capabilities - // (later though, after tablet mouse is fixed and coalescing is in place) + // (later though, after tablet mouse is fixed and (not) coalescing is in place) } else { + printf("leaving\n"); *tool_id_ptr = TOOL_ID_NONE; ct.Active = GHOST_kTabletModeNone; @@ -1434,7 +1448,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) { - NSEvent *event = (NSEvent *)eventPtr; + puts("tablet point"); + NSEvent *event = (NSEvent*)eventPtr; GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); @@ -1442,7 +1457,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + GHOST_TabletData& ct = window->GetCocoaTabletData(); ct.Pressure = [event pressure]; @@ -1450,46 +1465,107 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) ct.Xtilt = tilt.x; ct.Ytilt = tilt.y; + switch ([event type]) + { + case NSLeftMouseDown: + if (m_input_fidelity_hint == HI_FI) + { + printf("hi-fi on\n"); + [NSEvent setMouseCoalescingEnabled:NO]; + } + pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); + break; + case NSLeftMouseUp: + if (m_input_fidelity_hint == HI_FI) + { + printf("hi-fi off\n"); + [NSEvent setMouseCoalescingEnabled:YES]; + } + pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); + break; + default: + { + NSPoint pos = [event locationInWindow]; + pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y)); + break; + } + } + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { + printf("mouse "); NSEvent *event = (NSEvent *)eventPtr; GHOST_Window* window = (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); if (!window) { - //printf("\nW failure for event 0x%x",[event type]); + printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + + static float warp_dx = 0, warp_dy = 0; // need to reset these. e.g. each grab operation should get its own. + // ^^ not currently useful, try m_cursorDelta_* instead. + switch ([event type]) { case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: + printf("button down\n"); + if (m_input_fidelity_hint == HI_FI) + { + printf("hi-fi on\n"); + [NSEvent setMouseCoalescingEnabled:NO]; + } pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: + printf("button up\n"); + if (m_input_fidelity_hint == HI_FI) + { + printf("hi-fi off\n"); + [NSEvent setMouseCoalescingEnabled:YES]; + } pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); + // cheap hack, should reset when grab ends. + warp_dx = warp_dy = 0; break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: case NSMouseMoved: + { + NSPoint mousePos = [event locationInWindow]; + float event_dx = [event deltaX]; + float event_dy = [event deltaY]; + + bool coalesced = [NSEvent isMouseCoalescingEnabled]; + if (not coalesced) + printf("[hi-fi] "); + printf("move <%.2f,%.2f> to (%.2f,%.2f)\n", event_dx, event_dy, mousePos.x, mousePos.y); + + event_dy = -event_dy; //Strange Apple implementation (inverted coordinates for the deltaY) ... + + switch (window->getCursorGrabMode()) { case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move { + printf(" - grab hide\n"); GHOST_TInt32 x_warp, y_warp, x_accum, y_accum; window->getCursorGrabInitPos(x_warp, y_warp); window->getCursorGrabAccum(x_accum, y_accum); - x_accum += [event deltaX]; - y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ... + x_accum += event_dx; + y_accum += event_dy; window->setCursorGrabAccum(x_accum, y_accum); pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum)); @@ -1500,8 +1576,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; - GHOST_TInt32 event_dx = [event deltaX]; - GHOST_TInt32 event_dy = -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ... GHOST_TInt32 x_accum, y_accum, x_cur, y_cur; GHOST_Rect bounds, windowBounds, correctedBounds; @@ -1509,7 +1583,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); - //Switch back to Cocoa coordinates orientation (y=0 at bottom,the same as blender internal btw!), and to client coordinates + //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates window->getClientBounds(windowBounds); window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); @@ -1519,7 +1593,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); x_accum += event_dx - m_cursorDelta_x; - y_accum += event_dy - m_cursorDelta_y; + y_accum += event_dy - m_cursorDelta_y; window->setCursorGrabAccum(x_accum, y_accum); @@ -1544,15 +1618,18 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) default: { //Normal cursor operation: send mouse position in window - NSPoint mousePos = [event locationInWindow]; pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y)); m_cursorDelta_x=0; m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter + + warp_dx = 0; + warp_dy = 0; } break; } break; - + } + case NSScrollWheel: { /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ @@ -1607,8 +1684,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) m_isGestureInProgress = false; break; default: + printf(" unknown event type %d\n", [event type]); return GHOST_kFailure; - break; } return GHOST_kSuccess; -- cgit v1.2.3 From 12d7b10c10fd3636a7cb61909f12e4e10e8fe73d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 8 Jul 2010 01:53:36 +0000 Subject: added filtered event dispatch for lo-fi mouse/pen input --- intern/ghost/intern/GHOST_EventManager.cpp | 71 +++++++++++++++++++++++++++++- intern/ghost/intern/GHOST_EventManager.h | 8 ++++ intern/ghost/intern/GHOST_System.cpp | 10 ++--- intern/ghost/intern/GHOST_System.h | 1 + 4 files changed, 82 insertions(+), 8 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 0eeb2245cd0..8f5b5e74339 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -38,6 +38,10 @@ #include #include "GHOST_Debug.h" +// for testing lo-fi +#include "GHOST_EventPrinter.h" +#include +using namespace std; GHOST_EventManager::GHOST_EventManager() { @@ -81,7 +85,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) GHOST_IEvent* GHOST_EventManager::peekEvent() { GHOST_IEvent* event = 0; - if (m_events.size() > 0) { + if (!m_events.empty()) { event = m_events.back(); } return event; @@ -104,6 +108,24 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) +{ + // [mce] this variant switches the "handled" flag to work as described in the header + // it also stops after the first consumer has handled the event + bool handled = false; + if (event) { + TConsumerVector::iterator iter; + for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) { + if ((*iter)->processEvent(event)) { + handled = true; + // break; + } + } + } + return handled; +} + +#if 0 // disable to test a variant +bool GHOST_EventManager::dispatchEvent_original(GHOST_IEvent* event) { bool handled; if (event) { @@ -120,7 +142,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) } return handled; } - +#endif bool GHOST_EventManager::dispatchEvent() { @@ -152,6 +174,51 @@ bool GHOST_EventManager::dispatchEvents() } +bool GHOST_EventManager::dispatchEvents_lo_fi() +{ + if (m_events.empty()) + return false; + + bool allHandled = true; + GHOST_IEvent* cursorMove = NULL; + GHOST_IEvent* event = NULL; + + GHOST_EventPrinter printer; + + // when Pen gets its own event type, track it alongside mouse moves + // they probably won't both be active, but you never know + + cout << "\n--- lo-fi dispatch ---"; + cout << "\ndiscard:"; + while ((event = popEvent()) != NULL) { + if (event->getType() == GHOST_kEventCursorMove) { + // just a simple (x,y) pair, nothing much to adjust + // discard the older event and keep the latest + if (cursorMove) { + printer.processEvent(cursorMove); + delete cursorMove; + } + cursorMove = event; + } + else // not a cursor move event + if (!dispatchEvent(event)) + allHandled = false; + } + + // finally dispatch the single cursor update + if (cursorMove) { + cout << "\nsend:"; + printer.processEvent(cursorMove); + if (!dispatchEvent(cursorMove)) + allHandled = false; + } + + cout << endl; + + return allHandled; +} + + GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer) { GHOST_TSuccess success; diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index 40ba133e8fd..5071adb1bd4 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -108,6 +108,14 @@ public: */ virtual bool dispatchEvents(); + /** + * Dispatches most events on the stack, consolidating cursor moves into a single move. + * The event stack will be empty afterwards. + * @return Indicates whether all events were handled by some consumer. + */ + bool dispatchEvents_lo_fi(); + + /** * Adds a consumer to the list of event consumers. * @param consumer The consumer added to the list. diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 3cd3528eeb6..25b55345d46 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -198,7 +198,10 @@ bool GHOST_System::dispatchEvents() { bool handled; if (m_eventManager) { - handled = m_eventManager->dispatchEvents(); + if (m_input_fidelity_hint == LO_FI) + handled = m_eventManager->dispatchEvents_lo_fi(); + else + handled = m_eventManager->dispatchEvents(); } else { handled = false; @@ -283,11 +286,6 @@ GHOST_TSuccess GHOST_System::init() m_eventManager = new GHOST_EventManager (); m_ndofManager = new GHOST_NDOFManager(); -#if 0 - if(m_ndofManager) - printf("ndof manager \n"); -#endif - #ifdef GHOST_DEBUG if (m_eventManager) { m_eventPrinter = new GHOST_EventPrinter(); diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 6f570b33079..1aeb8597573 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -39,6 +39,7 @@ #include "GHOST_Buttons.h" #include "GHOST_ModifierKeys.h" #include "GHOST_EventManager.h" + #ifdef GHOST_DEBUG #include "GHOST_EventPrinter.h" #endif // GHOST_DEBUG -- cgit v1.2.3 From 56b287bfe6ec4be9a1b5a5ea36f330aec0bf61cf Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 11:54:24 +0000 Subject: disabled lo-fi dispatch log to reduce event debugging noise --- intern/ghost/intern/GHOST_EventManager.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 8f5b5e74339..bc0d7ada74d 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -183,19 +183,19 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() GHOST_IEvent* cursorMove = NULL; GHOST_IEvent* event = NULL; - GHOST_EventPrinter printer; +// GHOST_EventPrinter printer; // when Pen gets its own event type, track it alongside mouse moves // they probably won't both be active, but you never know - cout << "\n--- lo-fi dispatch ---"; - cout << "\ndiscard:"; +// cout << "\n--- lo-fi dispatch ---"; +// cout << "\ndiscard:"; while ((event = popEvent()) != NULL) { if (event->getType() == GHOST_kEventCursorMove) { // just a simple (x,y) pair, nothing much to adjust // discard the older event and keep the latest if (cursorMove) { - printer.processEvent(cursorMove); +// printer.processEvent(cursorMove); delete cursorMove; } cursorMove = event; @@ -207,13 +207,13 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() // finally dispatch the single cursor update if (cursorMove) { - cout << "\nsend:"; - printer.processEvent(cursorMove); +// cout << "\nsend:"; +// printer.processEvent(cursorMove); if (!dispatchEvent(cursorMove)) allHandled = false; } - cout << endl; +// cout << endl; return allHandled; } -- cgit v1.2.3 From 5b1925afba72dc4535cb889e50ecc642cf50c5b8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 12:12:52 +0000 Subject: Improved tablet support on Windows. Nice deep queue for input points. Much more is being captured now. WT_PACKET events are disabled until I can revisit in a day or two. Also added Wacom's driver wrappers, with their permission. These won't live here very long, but the WindowWin32 tablet code uses it for now. --- intern/ghost/intern/GHOST_WindowWin32.cpp | 81 ++++++------- intern/ghost/intern/GHOST_WindowWin32.h | 8 +- intern/ghost/intern/Utils.c | 182 ++++++++++++++++++++++++++++++ intern/ghost/intern/Utils.h | 94 +++++++++++++++ 4 files changed, 325 insertions(+), 40 deletions(-) create mode 100644 intern/ghost/intern/Utils.c create mode 100644 intern/ghost/intern/Utils.h (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 945e4c16a39..757d9d962fd 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -39,6 +39,10 @@ #include "GHOST_SystemWin32.h" #include "GHOST_DropTargetWin32.h" +//#include "wintab.h" // for tablets, naturally +#include "Utils.c" // that's right, .c, with permission from Wacom +#include // for debug, remove soon [mce] + // Need glew for some defines #include #include @@ -122,7 +126,7 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_hasMouseCaptured(false), m_nPressedButtons(0), m_customCursor(0), - m_wintab(NULL), + m_wintab(false), m_tabletData(NULL), m_tablet(0), m_maxPressure(0), @@ -238,14 +242,11 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } - m_wintab = ::LoadLibrary("Wintab32.dll"); + m_wintab = LoadWintab(); if (m_wintab) { - GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" ); - GHOST_WIN32_WTOpen fpWTOpen = ( GHOST_WIN32_WTOpen ) ::GetProcAddress( m_wintab, "WTOpenA" ); - // let's see if we can initialize tablet here /* check if WinTab available. */ - if (fpWTInfo && fpWTInfo(0, 0, NULL)) { + if (gpWTInfoA(0, 0, NULL)) { // Now init the tablet LOGCONTEXT lc; AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */ @@ -253,26 +254,27 @@ GHOST_WindowWin32::GHOST_WindowWin32( // Open a Wintab context // Get default context information - fpWTInfo( WTI_DEFCONTEXT, 0, &lc ); + gpWTInfoA( WTI_DEFCONTEXT, 0, &lc ); // Open the context lc.lcPktData = PACKETDATA; lc.lcPktMode = PACKETMODE; - lc.lcOptions |= CXO_MESSAGES | CXO_SYSTEM; + lc.lcOptions |= /* CXO_MESSAGES | */ CXO_SYSTEM; + lc.lcOptions &= ~CXO_MESSAGES; /* Set the entire tablet as active */ - fpWTInfo(WTI_DEVICES,DVC_X,&TabletX); - fpWTInfo(WTI_DEVICES,DVC_Y,&TabletY); + gpWTInfoA(WTI_DEVICES,DVC_X,&TabletX); + gpWTInfoA(WTI_DEVICES,DVC_Y,&TabletY); /* get the max pressure, to divide into a float */ - BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure); + BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); if (pressureSupport) m_maxPressure = Pressure.axMax; else m_maxPressure = 0; /* get the max tilt axes, to divide into floats */ - BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation); + BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); if (tiltSupport) { /* does the tablet support azimuth ([0]) and altitude ([1]) */ if (Orientation[0].axResolution && Orientation[1].axResolution) { @@ -285,12 +287,16 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } - if (fpWTOpen) { - m_tablet = fpWTOpen( m_hWnd, &lc, TRUE ); - if (m_tablet) { - m_tabletData = new GHOST_TabletData(); - m_tabletData->Active = GHOST_kTabletModeNone; - } + m_tablet = gpWTOpenA( m_hWnd, &lc, TRUE ); + if (m_tablet) { + m_tabletData = new GHOST_TabletData(); + m_tabletData->Active = GHOST_kTabletModeNone; + + // request a deep queue, to capture every pen point + int tabletQueueSize = 128; + while (!gpWTQueueSizeSet(m_tablet, tabletQueueSize)) + --tabletQueueSize; + printf("tablet queue size: %d\n", tabletQueueSize); } } } @@ -300,14 +306,12 @@ GHOST_WindowWin32::GHOST_WindowWin32( GHOST_WindowWin32::~GHOST_WindowWin32() { if (m_wintab) { - GHOST_WIN32_WTClose fpWTClose = ( GHOST_WIN32_WTClose ) ::GetProcAddress( m_wintab, "WTClose" ); - if (fpWTClose) { - if (m_tablet) - fpWTClose(m_tablet); - if (m_tabletData) - delete m_tabletData; - m_tabletData = NULL; - } + if (m_tablet) + gpWTClose(m_tablet); + if (m_tabletData) + delete m_tabletData; + m_tabletData = NULL; + UnloadWintab(); } if (m_customCursor) { DestroyCursor(m_customCursor); @@ -912,20 +916,16 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur void GHOST_WindowWin32::processWin32TabletInitEvent() { if (m_wintab) { - GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" ); - // let's see if we can initialize tablet here - /* check if WinTab available. */ - if (fpWTInfo) { AXIS Pressure, Orientation[3]; /* The maximum tablet size */ - BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure); + BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); if (pressureSupport) m_maxPressure = Pressure.axMax; else m_maxPressure = 0; - BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation); + BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); if (tiltSupport) { /* does the tablet support azimuth ([0]) and altitude ([1]) */ if (Orientation[0].axResolution && Orientation[1].axResolution) { @@ -938,17 +938,22 @@ void GHOST_WindowWin32::processWin32TabletInitEvent() } m_tabletData->Active = GHOST_kTabletModeNone; - } } } void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) { - PACKET pkt; +// PACKET pkt; if (m_wintab) { - GHOST_WIN32_WTPacket fpWTPacket = ( GHOST_WIN32_WTPacket ) ::GetProcAddress( m_wintab, "WTPacket" ); - if (fpWTPacket) { - if (fpWTPacket((HCTX)lParam, wParam, &pkt)) { + printf("tablet event "); + PACKET pkt_buffer[128]; + int n = gpWTPacketsGet((HCTX)lParam, 128, pkt_buffer); + printf("(%d in queue) ", n); + for (int i = 0; i < n; ++i) { + PACKET& pkt = pkt_buffer[i]; + // "while" not "if" -- drain the queue! +// while (gpWTPacket((HCTX)lParam, wParam, &pkt)) { + putchar('.'); if (m_tabletData) { switch (pkt.pkCursor) { case 0: /* first device */ @@ -1008,7 +1013,7 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) } } } - } + putchar('\n'); } } diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a4d31f87ffa..da3c47c39ac 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -39,9 +39,10 @@ #include "GHOST_Window.h" +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include - #include #define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) #define PACKETMODE PK_BUTTONS @@ -50,11 +51,13 @@ class GHOST_SystemWin32; class GHOST_DropTargetWin32; +/* // typedefs for WinTab functions to allow dynamic loading typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID ); typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL); typedef BOOL (API * GHOST_WIN32_WTClose) (HCTX); typedef BOOL (API * GHOST_WIN32_WTPacket) (HCTX, UINT, LPVOID); +*/ /** * GHOST window on M$ Windows OSs. @@ -328,7 +331,8 @@ protected: static const int s_maxTitleLength; /** WinTab dll handle */ - HMODULE m_wintab; +// HMODULE m_wintab; + bool m_wintab; /** Tablet data for GHOST */ GHOST_TabletData* m_tabletData; diff --git a/intern/ghost/intern/Utils.c b/intern/ghost/intern/Utils.c new file mode 100644 index 00000000000..05392793e21 --- /dev/null +++ b/intern/ghost/intern/Utils.c @@ -0,0 +1,182 @@ +/*---------------------------------------------------------------------------- + + NAME + Utils.c + + PURPOSE + Some general-purpose functions for the WinTab demos. + + COPYRIGHT + Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved + All rights reserved. + +---------------------------------------------------------------------------- */ + +#include "Utils.h" + +#ifdef WACOM_DEBUG + +void WacomTrace( char *lpszFormat, ...); + +#define WACOM_ASSERT( x ) assert( x ) +#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) +#else +#define WACOM_TRACE(...) +#define WACOM_ASSERT( x ) + +#endif // WACOM_DEBUG + +////////////////////////////////////////////////////////////////////////////// +HINSTANCE ghWintab = NULL; + +WTINFOA gpWTInfoA = NULL; +WTOPENA gpWTOpenA = NULL; +WTGETA gpWTGetA = NULL; +WTSETA gpWTSetA = NULL; +WTCLOSE gpWTClose = NULL; +WTPACKET gpWTPacket = NULL; +WTENABLE gpWTEnable = NULL; +WTOVERLAP gpWTOverlap = NULL; +WTSAVE gpWTSave = NULL; +WTCONFIG gpWTConfig = NULL; +WTRESTORE gpWTRestore = NULL; +WTEXTSET gpWTExtSet = NULL; +WTEXTGET gpWTExtGet = NULL; +WTQUEUESIZESET gpWTQueueSizeSet = NULL; +WTDATAPEEK gpWTDataPeek = NULL; +WTPACKETSGET gpWTPacketsGet = NULL; + +// TODO - add more wintab32 function pointers as needed + +char* pszProgramName = NULL; + +#define GETPROCADDRESS(type, func) \ + gp##func = (type)GetProcAddress(ghWintab, #func); \ + if (!gp##func){ WACOM_ASSERT(FALSE); UnloadWintab(); return FALSE; } + +////////////////////////////////////////////////////////////////////////////// +// Purpose +// Find wintab32.dll and load it. +// Find the exported functions we need from it. +// +// Returns +// TRUE on success. +// FALSE on failure. +// +BOOL LoadWintab( void ) +{ + ghWintab = LoadLibraryA( "Wintab32.dll" ); + if ( !ghWintab ) + { + DWORD err = GetLastError(); + WACOM_TRACE("LoadLibrary error: %i\n", err); + ShowError("Could not load Wintab32.dll"); + return FALSE; + } + + // Explicitly find the exported Wintab functions in which we are interested. + // We are using the ASCII, not unicode versions (where applicable). + GETPROCADDRESS( WTOPENA, WTOpenA ); + GETPROCADDRESS( WTINFOA, WTInfoA ); + GETPROCADDRESS( WTGETA, WTGetA ); + GETPROCADDRESS( WTSETA, WTSetA ); + GETPROCADDRESS( WTPACKET, WTPacket ); + GETPROCADDRESS( WTCLOSE, WTClose ); + GETPROCADDRESS( WTENABLE, WTEnable ); + GETPROCADDRESS( WTOVERLAP, WTOverlap ); + GETPROCADDRESS( WTSAVE, WTSave ); + GETPROCADDRESS( WTCONFIG, WTConfig ); + GETPROCADDRESS( WTRESTORE, WTRestore ); + GETPROCADDRESS( WTEXTSET, WTExtSet ); + GETPROCADDRESS( WTEXTGET, WTExtGet ); + GETPROCADDRESS( WTQUEUESIZESET, WTQueueSizeSet ); + GETPROCADDRESS( WTDATAPEEK, WTDataPeek ); + GETPROCADDRESS( WTPACKETSGET, WTPacketsGet ); + + + // TODO - don't forget to NULL out pointers in UnloadWintab(). + return TRUE; +} + + + +////////////////////////////////////////////////////////////////////////////// +// Purpose +// Uninitializes use of wintab32.dll +// +// Returns +// Nothing. +// +void UnloadWintab( void ) +{ + WACOM_TRACE( "UnloadWintab()\n" ); + + if ( ghWintab ) + { + FreeLibrary( ghWintab ); + ghWintab = NULL; + } + + gpWTOpenA = NULL; + gpWTClose = NULL; + gpWTInfoA = NULL; + gpWTPacket = NULL; + gpWTEnable = NULL; + gpWTOverlap = NULL; + gpWTSave = NULL; + gpWTConfig = NULL; + gpWTGetA = NULL; + gpWTSetA = NULL; + gpWTRestore = NULL; + gpWTExtSet = NULL; + gpWTExtGet = NULL; + gpWTQueueSizeSet = NULL; + gpWTDataPeek = NULL; + gpWTPacketsGet = NULL; +} + + + +////////////////////////////////////////////////////////////////////////////// +// Purpose +// Display error to user. +// +void ShowError( char *pszErrorMessage ) +{ + WACOM_TRACE( "ShowError()\n" ); + + WACOM_ASSERT( pszErrorMessage ); + + MessageBoxA( NULL, pszErrorMessage, gpszProgramName, MB_OK | MB_ICONHAND ); +} + + + +#ifdef WACOM_DEBUG + +////////////////////////////////////////////////////////////////////////////// + +void WacomTrace( char *lpszFormat, ...) +{ + char szTraceMessage[ 128 ]; + + int nBytesWritten; + + va_list args; + + WACOM_ASSERT( lpszFormat ); + + va_start( args, lpszFormat ); + + nBytesWritten = _vsnprintf( szTraceMessage, sizeof( szTraceMessage ) - 1, + lpszFormat, args ); + + if ( nBytesWritten > 0 ) + { + OutputDebugStringA( szTraceMessage ); + } + + va_end( args ); +} + +#endif // WACOM_DEBUG diff --git a/intern/ghost/intern/Utils.h b/intern/ghost/intern/Utils.h new file mode 100644 index 00000000000..e886389796f --- /dev/null +++ b/intern/ghost/intern/Utils.h @@ -0,0 +1,94 @@ +/*---------------------------------------------------------------------------- + + NAME + Utils.h + + PURPOSE + Defines for the general-purpose functions for the WinTab demos. + + COPYRIGHT + Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved + All rights reserved. + +---------------------------------------------------------------------------- */ +#pragma once + +#include +#include +#include +#include + +#include // NOTE: get from wactab header package + + +////////////////////////////////////////////////////////////////////////////// +#define WACOM_DEBUG + +// Ignore warnings about using unsafe string functions. +#pragma warning( disable : 4996 ) + +////////////////////////////////////////////////////////////////////////////// +// Function pointers to Wintab functions exported from wintab32.dll. +typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); +typedef HCTX ( API * WTOPENA )( HWND, LPLOGCONTEXTA, BOOL ); +typedef BOOL ( API * WTGETA ) ( HCTX, LPLOGCONTEXT ); +typedef BOOL ( API * WTSETA ) ( HCTX, LPLOGCONTEXT ); +typedef BOOL ( API * WTCLOSE ) ( HCTX ); +typedef BOOL ( API * WTENABLE ) ( HCTX, BOOL ); +typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); +typedef BOOL ( API * WTOVERLAP ) ( HCTX, BOOL ); +typedef BOOL ( API * WTSAVE ) ( HCTX, LPVOID ); +typedef BOOL ( API * WTCONFIG ) ( HCTX, HWND ); +typedef HCTX ( API * WTRESTORE ) ( HWND, LPVOID, BOOL ); +typedef BOOL ( API * WTEXTSET ) ( HCTX, UINT, LPVOID ); +typedef BOOL ( API * WTEXTGET ) ( HCTX, UINT, LPVOID ); +typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); +typedef int ( API * WTDATAPEEK ) ( HCTX, UINT, UINT, int, LPVOID, LPINT); +typedef int ( API * WTPACKETSGET ) (HCTX, int, LPVOID); + +// TODO - add more wintab32 function defs as needed + +////////////////////////////////////////////////////////////////////////////// +extern char* gpszProgramName; + +// Loaded Wintab32 API functions. +extern HINSTANCE ghWintab; + +extern WTINFOA gpWTInfoA; +extern WTOPENA gpWTOpenA; +extern WTGETA gpWTGetA; +extern WTSETA gpWTSetA; +extern WTCLOSE gpWTClose; +extern WTPACKET gpWTPacket; +extern WTENABLE gpWTEnable; +extern WTOVERLAP gpWTOverlap; +extern WTSAVE gpWTSave; +extern WTCONFIG gpWTConfig; +extern WTRESTORE gpWTRestore; +extern WTEXTSET gpWTExtSet; +extern WTEXTGET gpWTExtGet; +extern WTQUEUESIZESET gpWTQueueSizeSet; +extern WTDATAPEEK gpWTDataPeek; +extern WTPACKETSGET gpWTPacketsGet; + +// TODO - add more wintab32 function pointers as needed + +////////////////////////////////////////////////////////////////////////////// +BOOL LoadWintab( void ); +void UnloadWintab( void ); + +void ShowError( char *pszErrorMessage ); + +////////////////////////////////////////////////////////////////////////////// +#ifdef WACOM_DEBUG + +void WacomTrace( char *lpszFormat, ...); + +#define WACOM_ASSERT( x ) assert( x ) +#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) +#else +#define WACOM_TRACE(...) +#define WACOM_ASSERT( x ) + +#endif // WACOM_DEBUG + -- cgit v1.2.3 From 7aa8ae37819b4a95910089c27fa1e6d704a0f907 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 12:24:14 +0000 Subject: Hi-fi mouse input on Windows! The remains of a RawInput mouse attempt are included, but disabled. RawInput will still be used for multi-axis devices. Eliminated the need for several #defines by requiring WinXP or newer. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 422 ++++++++++++++++++++++++------ intern/ghost/intern/GHOST_SystemWin32.h | 34 ++- 2 files changed, 375 insertions(+), 81 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 76ce7703c06..76300b85242 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -37,6 +37,8 @@ #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" +#include // for debug [mce] + // win64 doesn't define GWL_USERDATA #ifdef WIN32 #ifndef GWL_USERDATA @@ -49,31 +51,16 @@ * According to the docs the mouse wheel message is supported from windows 98 * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the * wheel detent value are undefined. - */ + + [mce] able to remove this too? + #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x020A #endif // WM_MOUSEWHEEL #ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */ +#define WHEEL_DELTA 120 // Value for rolling one detent, (old convention! MS changed it) #endif // WHEEL_DELTA - -/* - * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2. - * MSDN: Declared in Winuser.h, include Windows.h - * This does not seem to work with MinGW so we define our own here. */ -#ifndef XBUTTON1 -#define XBUTTON1 0x0001 -#endif // XBUTTON1 -#ifndef XBUTTON2 -#define XBUTTON2 0x0002 -#endif // XBUTTON2 -#ifndef WM_XBUTTONUP -#define WM_XBUTTONUP 524 -#endif // WM_XBUTTONUP -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 523 -#endif // WM_XBUTTONDOWN #include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" @@ -135,9 +122,31 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_displayManager = new GHOST_DisplayManagerWin32 (); GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); m_displayManager->initialize(); - + // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); + + m_input_fidelity_hint = HI_FI; // just for testing... + +/* + // register for RawInput devices + RAWINPUTDEVICE devices[2]; + + // standard HID mouse + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x02; + devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages + devices[0].hwndTarget = NULL; + + // multi-axis mouse (SpaceNavigator) + devices[1].usUsagePage = 0x01; + devices[1].usUsage = 0x08; + devices[1].dwFlags = 0; + devices[1].hwndTarget = NULL; + + if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE))) + puts("registered for raw mouse and multi-axis input"); +*/ } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -513,13 +522,15 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, } -GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow) +GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y) { GHOST_TInt32 x_screen, y_screen; GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; - system->getCursorPosition(x_screen, y_screen); +// system->getCursorPosition(x_screen, y_screen); + x_screen = x; + y_screen = y; if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) { @@ -546,7 +557,7 @@ GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new)); }else{ return new GHOST_EventCursor(system->getMilliSeconds(), - GHOST_kEventCursorMove, + type, window, x_screen + x_accum, y_screen + y_accum @@ -556,7 +567,7 @@ GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, } else { return new GHOST_EventCursor(system->getMilliSeconds(), - GHOST_kEventCursorMove, + type, window, x_screen, y_screen @@ -628,23 +639,199 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } +bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y) +{ + GHOST_IEvent* event = NULL; + bool eventSent = false; + + puts("BEGIN"); + + if (raw.header.dwType == RIM_TYPEMOUSE) + { + USHORT const& buttonFlags = raw.data.mouse.usButtonFlags; + if (buttonFlags) + { + printf("button flags: %04X\n", buttonFlags); + + if (buttonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) + { + puts("left button down"); + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); + } + else if (buttonFlags & RI_MOUSE_LEFT_BUTTON_UP) + { + puts("left button up"); + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + } + + if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) + { + puts("right button down"); + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); + } + else if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_UP) + { + puts("right button up"); + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); + } + + if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) + { + puts("middle button down"); + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); + } + else if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) + { + puts("middle button up"); + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); + } + + // similar for BUTTON_4 and BUTTON_5 + + if (buttonFlags & RI_MOUSE_WHEEL) + { + signed short wheelDelta = raw.data.mouse.usButtonData; + printf("wheel moved %+d\n", wheelDelta); + } + } + + int dx = raw.data.mouse.lLastX; // These might be in Mickeys, not pixels. + int dy = raw.data.mouse.lLastY; + if (dx || dy) + { + printf("mouse moved (%+d,%+d)\n", dx, dy); + x += dx; + x += dy; + event = processCursorEvent(GHOST_kEventCursorMove, window, x, y); + } + } + else + puts("exotic device!"); + + // assume only one event will come from this RawInput report + // test and adjust assumptions as needed! + + if (event) + { + pushEvent(event); + event = NULL; + eventSent = true; + } + + puts("END"); + + return eventSent; +} + +int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, int yPrev, GHOST_WindowWin32* window) + { + MOUSEMOVEPOINT point = { + xLatest & 0x0000FFFF, // confine to low word to make GetMouseMovePointsEx happy + yLatest & 0x0000FFFF, + 0, // time stamp unknown + NULL // no extra info + }; + + MOUSEMOVEPOINT morePoints[64]; + + int n = GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &point, morePoints, 64, GMMP_USE_DISPLAY_POINTS); + if (n == -1) + { + printf(" can't get more mouse points (error %d)\n", (int) GetLastError()); + return 0; + } + + // search for 'prev' point (we want only newer points) + for (int i = 1; i < n; ++i) + if (morePoints[i].x == xPrev && morePoints[i].y == yPrev) + { + n = i; // don't include found point (or more ancient points) + break; + } + + for (int i = n - 1; i > 0; --i) + { + signed short x = morePoints[i].x; + signed short y = morePoints[i].y; + + printf("> (%d,%d)\n", x, y); + + pushEvent(processCursorEvent(GHOST_kEventCursorMove, window, x, y)); + } + + return n; + } // END getMoreMousePoints LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - GHOST_Event* event = 0; LRESULT lResult = 0; GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") + // [mce] then why not register this function at the end of SystemWin32 constructor? + + bool handled = false; if (hwnd) { GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA); if (window) { + handled = system->handleEvent(window, msg, wParam, lParam); + + // take care of misc. cases that need hwnd + if (msg == WM_ACTIVATE) + /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL + will not be dispatched to OUR active window if we minimize one of OUR windows. */ + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); + else if (msg == WM_PAINT) + /* An application sends the WM_PAINT message when the system or another application + * makes a request to paint a portion of an application's window. The message is sent + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * function when the application obtains a WM_PAINT message by using the GetMessage or + * PeekMessage function. */ + ::ValidateRect(hwnd, NULL); + } + else { + // Event found for a window before the pointer to the class has been set. + GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n") + + /* These are events we typically miss at this point: + WM_GETMINMAXINFO 0x24 + WM_NCCREATE 0x81 + WM_NCCALCSIZE 0x83 + WM_CREATE 0x01 + We let DefWindowProc do the work. + */ + } + } + else { + // Events without valid hwnd + GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") + } + + if (!handled) + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); + + return lResult; +} + +bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam) + { + GHOST_Event* event = NULL; + bool eventSent = false; + + static int mousePosX = 0, mousePosY = 0; // track mouse position between calls + switch (msg) { //////////////////////////////////////////////////////////////////////// // Keyboard events, processed //////////////////////////////////////////////////////////////////////// case WM_KEYDOWN: - /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a + /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt * key is not pressed. */ @@ -660,33 +847,33 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case VK_SHIFT: case VK_CONTROL: case VK_MENU: - if (!system->m_separateLeftRightInitialized) { + if (!m_separateLeftRightInitialized) { // Check whether this system supports separate left and right keys switch (wParam) { case VK_SHIFT: - system->m_separateLeftRight = + m_separateLeftRight = (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? true : false; break; case VK_CONTROL: - system->m_separateLeftRight = + m_separateLeftRight = (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? true : false; break; case VK_MENU: - system->m_separateLeftRight = + m_separateLeftRight = (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? true : false; break; } - system->m_separateLeftRightInitialized = true; + m_separateLeftRightInitialized = true; } - system->processModifierKeys(window); + processModifierKeys(window); // Bypass call to DefWindowProc - return 0; + return true; default: event = processKeyEvent(window, true, wParam, lParam); if (!event) { @@ -704,9 +891,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case VK_SHIFT: case VK_CONTROL: case VK_MENU: - system->processModifierKeys(window); + processModifierKeys(window); // Bypass call to DefWindowProc - return 0; + return true; default: event = processKeyEvent(window, false, wParam, lParam); if (!event) { @@ -718,6 +905,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; +#if 0 // this code is illustrative; no need to compile //////////////////////////////////////////////////////////////////////// // Keyboard events, ignored //////////////////////////////////////////////////////////////////////// @@ -742,16 +930,21 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * a dead key that is pressed while holding down the alt key. */ break; +#endif // illustrative code + //////////////////////////////////////////////////////////////////////// // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam); + puts("WT_PACKET"); + window->processWin32TabletEvent(wParam, lParam); break; case WT_CSRCHANGE: case WT_PROXIMITY: - ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent(); + window->processWin32TabletInitEvent(); break; + +//#if 0 // this code has been replaced by RawInput (the WM_INPUT case) //////////////////////////////////////////////////////////////////////// // Mouse events, processed //////////////////////////////////////////////////////////////////////// @@ -795,14 +988,100 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); } break; +//#endif // replaced mouse code + case WM_MOUSEMOVE: - event = processCursorEvent(GHOST_kEventCursorMove, window); + { +// puts("WM_MOUSEMOVE"); + +// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs + int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + if (tabletTool) + puts("(from tablet)"); + else + { + // these give window coords, we need view coords +// mousePosX = LOWORD(lParam); +// mousePosY = HIWORD(lParam); +// window->clientToScreen(mousePosX, mousePosY, mousePosX, mousePosY); + + int xPrev = mousePosX; + int yPrev = mousePosY; + window->clientToScreen(LOWORD(lParam), HIWORD(lParam), mousePosX, mousePosY); + // if (m_input_fidelity_hint == HI_FI) // can't access hint from static function + + putchar('\n'); + /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); +// printf("%d more mouse points found\n", n); + printf(" (%d,%d)\n", mousePosX, mousePosY); + + event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); + } break; + } + + case WM_INPUT: + puts("WM_INPUT"); +{ +/* + UINT dwSize; + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + LPBYTE lpb = new BYTE[dwSize]; + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); + RAWINPUT* raw = (RAWINPUT*)lpb; +*/ + + RAWINPUT raw; + RAWINPUT* raw_ptr = &raw; + UINT rawSize = sizeof(RAWINPUT); +// UINT bufferSize = rawSize; + + puts("processing first event:"); + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); + eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); + +// GetRawInputBuffer(NULL, &bufferSize, sizeof(RAWINPUTHEADER)); +// UINT n = bufferSize / rawSize; +// printf("allocating %d bytes (room for %d events)\n", bufferSize, n); + + RAWINPUT rawBuffer[10];// = new RAWINPUT[n]; + rawSize *= 10; + while (true) + { + int n = GetRawInputBuffer(rawBuffer, &rawSize, sizeof(RAWINPUTHEADER)); + if (n == -1) + { + printf(" error %d\n", (int) GetLastError()); + break; + } + else if (n == 0) + { + //puts("no more events"); + putchar('\n'); + break; + } + else + { + printf("processing %d more events:\n", n); + for (int i = 0; i < n; ++i) + { + RAWINPUT const& raw = rawBuffer[i]; + eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + } + + // clear processed events from the queue + DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); + } + } // inf. loop +} + break; case WM_MOUSEWHEEL: - /* The WM_MOUSEWHEEL message is sent to the focus window - * when the mouse wheel is rotated. The DefWindowProc + puts("WM_MOUSEWHEEL"); + /* The WM_MOUSEWHEEL message is sent to the focus window + * when the mouse wheel is rotated. The DefWindowProc * function propagates the message to the window's parent. - * There should be no internal forwarding of the message, + * There should be no internal forwarding of the message, * since DefWindowProc propagates it up the parent chain * until it finds a window that processes it. */ @@ -827,6 +1106,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; +#if 0 // this code is illustrative; no need to compile //////////////////////////////////////////////////////////////////////// // Mouse events, ignored //////////////////////////////////////////////////////////////////////// @@ -842,6 +1122,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * is sent to the window that has captured the mouse. */ break; +#endif // illustrative code //////////////////////////////////////////////////////////////////////// // Window events, processed @@ -858,19 +1139,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * the message is sent asynchronously, so the window is activated immediately. */ event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); - /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL - will not be dispatched to OUR active window if we minimize one of OUR windows. */ - lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; case WM_PAINT: - /* An application sends the WM_PAINT message when the system or another application + /* An application sends the WM_PAINT message when the system or another application * makes a request to paint a portion of an application's window. The message is sent * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage * function when the application obtains a WM_PAINT message by using the GetMessage or * PeekMessage function. */ event = processWindowEvent(GHOST_kEventWindowUpdate, window); - ::ValidateRect(hwnd, NULL); break; case WM_GETMINMAXINFO: /* The WM_GETMINMAXINFO message is sent to a window when the size or @@ -906,6 +1183,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, */ event = processWindowEvent(GHOST_kEventWindowMove, window); break; + +#if 0 // this code is illustrative; no need to compile //////////////////////////////////////////////////////////////////////// // Window events, ignored //////////////////////////////////////////////////////////////////////// @@ -986,57 +1265,44 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * In GHOST, we let DefWindowProc call the timer callback. */ break; +#endif // illustrative code + +#if 0 // this is part of the 'old' NDOF system; new one coming soon! case WM_BLND_NDOF_AXIS: { GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> + m_ndofManager->GHOST_NDOFGetDatas(ndofdata); + m_eventManager-> pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFMotion, + getMilliSeconds(), + GHOST_kEventNDOFMotion, window, ndofdata)); } break; case WM_BLND_NDOF_BTN: { GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> + m_ndofManager->GHOST_NDOFGetDatas(ndofdata); + m_eventManager-> pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFButton, + getMilliSeconds(), + GHOST_kEventNDOFButton, window, ndofdata)); } break; +#endif // old NDOF } + + if (!eventSent) + if (event) { + pushEvent(event); + eventSent = true; } - else { - // Event found for a window before the pointer to the class has been set. - GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n") - /* These are events we typically miss at this point: - WM_GETMINMAXINFO 0x24 - WM_NCCREATE 0x81 - WM_NCCALCSIZE 0x83 - WM_CREATE 0x01 - We let DefWindowProc do the work. - */ - } - } - else { - // Events without valid hwnd - GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") - } - if (event) { - system->pushEvent(event); - } - else { - lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); - } - return lResult; + return eventSent; } -GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const +GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const { char *buffer; char *temp_buff; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index e65393a4faa..2fe5e2f4d95 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -37,7 +37,10 @@ #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include +#include #include "GHOST_System.h" @@ -53,6 +56,8 @@ class GHOST_EventWheel; class GHOST_EventWindow; class GHOST_EventDragnDrop; +class GHOST_WindowWin32; + /** * WIN32 Implementation of GHOST_System class. * @see GHOST_System. @@ -258,9 +263,10 @@ protected: * Creates cursor event. * @param type The type of event to create. * @param window The window receiving the event (the active window). + * @param x,y Cursor position. * @return The event created. */ - static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow); + static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y); /** * Creates a mouse wheel event. @@ -287,12 +293,31 @@ protected: * @return The event created. */ static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); - /** + + /** * Handles minimum window size. * @param minmax The MINMAXINFO structure. */ static void processMinMaxInfo(MINMAXINFO * minmax); - + + /** + * Creates and sends mouse or multi-axis events. + * @param raw a single RawInput structure + * @param window The window receiving the event (the active window). + * @param x,y current mouse coordinates, which may be updated by this function + * @return Whether any events (possibly more than one) were created and sent. + */ + bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y); + + /** + * Creates and sends mouse events for mouse movements "in between" WM_MOUSEMOVEs. + * @param Latest screen coords from latest WM_MOUSEMOVE + * @param Prev screen coords from previous WM_MOUSEMOVE + * @param window The window receiving the event (the active window). + * @return How many events (possibly many) were created and sent. + */ + int getMoreMousePoints(int xLatest, int yLatest, int xPrev, int yPrev, GHOST_WindowWin32* window); + /** * Returns the local state of the modifier keys (from the message queue). * @param keys The state of the keys. @@ -311,6 +336,9 @@ protected: */ static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + // non-static version of WndProc + bool handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam); + /** The current state of the modifier keys. */ GHOST_ModifierKeys m_modifierKeys; /** State variable set at initialization. */ -- cgit v1.2.3 From f6730216e0b8d1f7a23fdf3e10565d0fc64c3f92 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 12:30:16 +0000 Subject: Tweak Windows #includes to require WinXP or newer and speed up build times. --- intern/ghost/intern/GHOST_DisplayManagerWin32.cpp | 4 ++++ intern/ghost/intern/GHOST_DropTargetWin32.h | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index 29d15d3e4de..916ddf81217 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -38,7 +38,11 @@ #include "GHOST_Debug.h" // We do not support multiple monitors at the moment + +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include + #define COMPILE_MULTIMON_STUBS #ifndef FREE_WINDOWS #include diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index 6fbf33ce9f8..039c8e8a313 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -28,7 +28,11 @@ #ifndef _GHOST_DROP_TARGET_WIN32_H_ #define _GHOST_DROP_TARGET_WIN32_H_ +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include +#include + #include #include #include "GHOST_WindowWin32.h" @@ -41,7 +45,7 @@ public: * Enables clients to get pointers to other interfaces on a given object * through the QueryInterface method, and manage the existence of the object * through the AddRef and Release methods. All other COM interfaces are - * inherited, directly or indirectly, from IUnknown. Therefore, the three + * inherited, directly or indirectly, from IUnknown. Therefore, the three * methods in IUnknown are the first entries in the VTable for every interface. */ HRESULT __stdcall QueryInterface (REFIID riid, void ** ppvObj); -- cgit v1.2.3 From 8a138f4ab2e871a062925044a80a97ae3349541b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 17 Jul 2010 05:49:41 +0000 Subject: fixed misspelled variable in Wacom utility --- intern/ghost/intern/Utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/Utils.c b/intern/ghost/intern/Utils.c index 05392793e21..d354750f7f6 100644 --- a/intern/ghost/intern/Utils.c +++ b/intern/ghost/intern/Utils.c @@ -48,7 +48,7 @@ WTPACKETSGET gpWTPacketsGet = NULL; // TODO - add more wintab32 function pointers as needed -char* pszProgramName = NULL; +char* gpszProgramName = NULL; #define GETPROCADDRESS(type, func) \ gp##func = (type)GetProcAddress(ghWintab, #func); \ -- cgit v1.2.3 From 14736cab162a93559bd8c12689356b94eaa2f9f3 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 17 Jul 2010 05:52:46 +0000 Subject: Added rudimentary SpaceNav event capture code for Windows. Disabled RawInput mouse code. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 112 ++++++++++++++++++++++++------ intern/ghost/intern/GHOST_SystemWin32.h | 2 +- 2 files changed, 90 insertions(+), 24 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 76300b85242..1b173208b18 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -128,25 +128,23 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_input_fidelity_hint = HI_FI; // just for testing... -/* // register for RawInput devices - RAWINPUTDEVICE devices[2]; - + RAWINPUTDEVICE devices[1]; +/* // standard HID mouse devices[0].usUsagePage = 0x01; devices[0].usUsage = 0x02; devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages devices[0].hwndTarget = NULL; - +*/ // multi-axis mouse (SpaceNavigator) - devices[1].usUsagePage = 0x01; - devices[1].usUsage = 0x08; - devices[1].dwFlags = 0; - devices[1].hwndTarget = NULL; + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x08; + devices[0].dwFlags = 0; + devices[0].hwndTarget = NULL; - if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE))) - puts("registered for raw mouse and multi-axis input"); -*/ + if (RegisterRawInputDevices(devices, 1, sizeof(RAWINPUTDEVICE))) + puts("registered for multi-axis input"); } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -639,13 +637,14 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } -bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y) +bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ) { GHOST_IEvent* event = NULL; bool eventSent = false; puts("BEGIN"); +#if 0 // now using the existing mouse button handlers, improved movement handler if (raw.header.dwType == RIM_TYPEMOUSE) { USHORT const& buttonFlags = raw.data.mouse.usButtonFlags; @@ -705,24 +704,89 @@ bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* int dy = raw.data.mouse.lLastY; if (dx || dy) { - printf("mouse moved (%+d,%+d)\n", dx, dy); + printf("mouse moved <%+d,%+d>\n", dx, dy); x += dx; x += dy; event = processCursorEvent(GHOST_kEventCursorMove, window, x, y); } } +#endif // unused experimental mouse code + + if (raw.header.dwType == RIM_TYPEHID) + { +// RID_DEVICE_INFO info; +// DWORD infoSize = sizeof(RID_DEVICE_INFO); +// int n = GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); + // ... and so on + // I'll finish this device checking code later. Since we ask for only multi-axis input + // in the constructor, that's all we should get here. + +/* +Here's some handy info from http://www.linux-usb.org/usb.ids + +vendor ID +046d Logitech, Inc. + + device IDs + c623 3Dconnexion Space Traveller 3D Mouse + c625 3Dconnexion Space Pilot 3D Mouse + c626 3Dconnexion Space Navigator 3D Mouse + c627 3Dconnexion Space Explorer 3D Mouse + +No other registered devices use the c62_ space, so a simple mask will work! +*/ + + short t[3], r[3]; // defined here just for quick testing, + unsigned short buttons; // will maintain shared copy for all NDOF events + + // multiple events per RAWHID? MSDN hints at this. + printf("%d events\n", raw.data.hid.dwCount); + + BYTE const* data = &raw.data.hid.bRawData; +// MinGW's definition (below) doesn't agree with MSDN reference for bRawData: +// typedef struct tagRAWHID { +// DWORD dwSizeHid; +// DWORD dwCount; +// BYTE bRawData; +// } RAWHID,*PRAWHID,*LPRAWHID; + + BYTE packetType = data[0]; + switch (packetType) + { + case 1: // translation + memcpy(t, data + 1, sizeof(t)); + printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + break; + case 2: // rotation + memcpy(r, data + 1, sizeof(r)); + printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + break; + case 3: // buttons + memcpy(&buttons, data + 1, sizeof(buttons)); + printf("buttons:"); + if (buttons) + { + // work our way through the bit mask + for (int i = 0; i < 16; ++i) + if (buttons & (1 << i)) + printf(" %d", i + 1); + printf("\n"); + } else - puts("exotic device!"); + printf(" none\n"); + break; + } + } // assume only one event will come from this RawInput report // test and adjust assumptions as needed! - if (event) - { - pushEvent(event); - event = NULL; - eventSent = true; - } + if (event) + { + pushEvent(event); + event = NULL; + eventSent = true; + } puts("END"); @@ -944,7 +1008,6 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM window->processWin32TabletInitEvent(); break; -//#if 0 // this code has been replaced by RawInput (the WM_INPUT case) //////////////////////////////////////////////////////////////////////// // Mouse events, processed //////////////////////////////////////////////////////////////////////// @@ -1037,8 +1100,11 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // UINT bufferSize = rawSize; puts("processing first event:"); + // I don't know if this is needed. Can we get by with just GetRawInputBuffer? + // Thought some mouse events were missing, so I put this in to be cautious. + // Test and remove if redundant. [mce] GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); - eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); // GetRawInputBuffer(NULL, &bufferSize, sizeof(RAWINPUTHEADER)); @@ -1067,7 +1133,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM for (int i = 0; i < n; ++i) { RAWINPUT const& raw = rawBuffer[i]; - eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); } // clear processed events from the queue diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 2fe5e2f4d95..8fae4d6ba78 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -307,7 +307,7 @@ protected: * @param x,y current mouse coordinates, which may be updated by this function * @return Whether any events (possibly more than one) were created and sent. */ - bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y); + bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ); /** * Creates and sends mouse events for mouse movements "in between" WM_MOUSEMOVEs. -- cgit v1.2.3 From 1a27b5a74d5f82e9199073f5bd8326be0f6d05f6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:07:28 +0000 Subject: removed unused Macintosh Carbon code --- intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp | 174 ----- intern/ghost/intern/GHOST_DisplayManagerCarbon.h | 116 ---- intern/ghost/intern/GHOST_WindowCarbon.cpp | 743 --------------------- intern/ghost/intern/GHOST_WindowCarbon.h | 312 --------- 4 files changed, 1345 deletions(-) delete mode 100644 intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp delete mode 100644 intern/ghost/intern/GHOST_DisplayManagerCarbon.h delete mode 100644 intern/ghost/intern/GHOST_WindowCarbon.cpp delete mode 100644 intern/ghost/intern/GHOST_WindowCarbon.h (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp deleted file mode 100644 index 2c92ef0e2fa..00000000000 --- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** - - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date September 21, 2001 - */ - -#include "GHOST_DisplayManagerCarbon.h" -#include "GHOST_Debug.h" - -// We do not support multiple monitors at the moment - - -GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(void) -{ - if (::CGGetActiveDisplayList(0, NULL, &m_numDisplays) != CGDisplayNoErr) - { - m_numDisplays = 0; - m_displayIDs = NULL; - } - if (m_numDisplays > 0) - { - m_displayIDs = new CGDirectDisplayID [m_numDisplays]; - GHOST_ASSERT((m_displayIDs!=NULL), "GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(): memory allocation failed"); - ::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays); - } -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplays(GHOST_TUns8& numDisplays) const -{ - numDisplays = (GHOST_TUns8) m_numDisplays; - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getNumDisplaySettings(): only main display is supported"); - - CFArrayRef displayModes; - displayModes = ::CGDisplayAvailableModes(m_displayIDs[display]); - CFIndex numModes = ::CFArrayGetCount(displayModes); - numSettings = (GHOST_TInt32)numModes; - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getDisplaySetting(): only main display is supported"); - - CFArrayRef displayModes; - CGDirectDisplayID d = m_displayIDs[display]; - displayModes = ::CGDisplayAvailableModes(d); - //CFIndex numModes = ::CFArrayGetCount(displayModes);/*unused*/ - //GHOST_TInt32 numSettings = (GHOST_TInt32)numModes; /*unused*/ - CFDictionaryRef displayModeValues = (CFDictionaryRef)::CFArrayGetValueAtIndex(displayModes, index); - - setting.xPixels = getValue(displayModeValues, kCGDisplayWidth); - setting.yPixels = getValue(displayModeValues, kCGDisplayHeight); - setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel); - setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate); - -#ifdef GHOST_DEBUG - printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency); -#endif // GHOST_DEBUG - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(): only main display is supported"); - - CFDictionaryRef displayModeValues = ::CGDisplayCurrentMode(m_displayIDs[display]); - - setting.xPixels = getValue(displayModeValues, kCGDisplayWidth); - setting.yPixels = getValue(displayModeValues, kCGDisplayHeight); - setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel); - setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate); - -#ifdef GHOST_DEBUG - printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency); -#endif // GHOST_DEBUG - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting) -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): only main display is supported"); - -#ifdef GHOST_DEBUG - printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): requested settings:\n"); - printf(" setting.xPixels=%d\n", setting.xPixels); - printf(" setting.yPixels=%d\n", setting.yPixels); - printf(" setting.bpp=%d\n", setting.bpp); - printf(" setting.frequency=%d\n", setting.frequency); -#endif // GHOST_DEBUG - - CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate( - m_displayIDs[display], - (size_t)setting.bpp, - (size_t)setting.xPixels, - (size_t)setting.yPixels, - (CGRefreshRate)setting.frequency, - NULL); - -#ifdef GHOST_DEBUG - printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): switching to:\n"); - printf(" setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth)); - printf(" setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight)); - printf(" setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel)); - printf(" setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate)); -#endif // GHOST_DEBUG - - CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues); - - return err == CGDisplayNoErr ? GHOST_kSuccess : GHOST_kFailure; -} - - -long GHOST_DisplayManagerCarbon::getValue(CFDictionaryRef values, CFStringRef key) const -{ - CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key); - - if (!numberValue) - { - return -1; - } - - long intValue; - - if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue)) - { - return -1; - } - - return intValue; -} - diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h deleted file mode 100644 index 5571efb68cb..00000000000 --- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** - * @file GHOST_DisplayManagerCarbon.h - * Declaration of GHOST_DisplayManagerCarbon class. - */ - -#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_ -#define _GHOST_DISPLAY_MANAGER_CARBON_H_ - -#ifndef __APPLE__ -#error Apple only! -#endif // __APPLE__ - -#include "GHOST_DisplayManager.h" - -#define __CARBONSOUND__ -#include - -/** - * Manages system displays (Mac OSX/Carbon implementation). - * @see GHOST_DisplayManager - * @author Maarten Gribnau - * @date September 21, 2001 - */ -class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager -{ -public: - /** - * Constructor. - */ - GHOST_DisplayManagerCarbon(void); - - /** - * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. - */ - virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; - - /** - * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The number of settings of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; - - /** - * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; - - /** - * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; - - /** - * Changes the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); - -protected: - /** - * Returns a value from a dictionary. - * @param values Dictionary to return value from. - * @param key Key to return value for. - * @return The value for this key. - */ - long getValue(CFDictionaryRef values, CFStringRef key) const; - - /** Cached number of displays. */ - CGDisplayCount m_numDisplays; - /** Cached display id's for each display. */ - CGDirectDisplayID* m_displayIDs; -}; - - -#endif // _GHOST_DISPLAY_MANAGER_CARBON_H_ - diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp deleted file mode 100644 index 376859d3e16..00000000000 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** - - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 10, 2001 - */ - -#include "GHOST_WindowCarbon.h" -#include "GHOST_Debug.h" - -AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL; -#ifdef GHOST_DRAW_CARBON_GUTTER -const GHOST_TInt32 GHOST_WindowCarbon::s_sizeRectSize = 16; -#endif //GHOST_DRAW_CARBON_GUTTER - -static const GLint sPreferredFormatWindow[8] = { -AGL_RGBA, -AGL_DOUBLEBUFFER, -AGL_ACCELERATED, -AGL_DEPTH_SIZE, 32, -AGL_NONE, -}; - -static const GLint sPreferredFormatFullScreen[9] = { -AGL_RGBA, -AGL_DOUBLEBUFFER, -AGL_ACCELERATED, -AGL_FULLSCREEN, -AGL_DEPTH_SIZE, 32, -AGL_NONE, -}; - - - -WindowRef ugly_hack=NULL; - -const EventTypeSpec kWEvents[] = { - { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */ -}; - -static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) { - WindowRef mywindow; - GHOST_WindowCarbon *ghost_window; - OSStatus err; - int theState; - - if (::GetEventKind(event) == kEventWindowZoom) { - err = ::GetEventParameter (event,kEventParamDirectObject,typeWindowRef,NULL,sizeof(mywindow),NULL, &mywindow); - ghost_window = (GHOST_WindowCarbon *) GetWRefCon(mywindow); - theState = ghost_window->getMac_windowState(); - if (theState == 1) - ghost_window->setMac_windowState(2); - else if (theState == 2) - ghost_window->setMac_windowState(1); - - } - return eventNotHandledErr; -} - -GHOST_WindowCarbon::GHOST_WindowCarbon( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - const bool stereoVisual, - const GHOST_TUns16 numOfAASamples -) : - GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone), - m_windowRef(0), - m_grafPtr(0), - m_aglCtx(0), - m_customCursor(0), - m_fullScreenDirty(false) -{ - Str255 title255; - OSStatus err; - - //fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width); - - if (state >= GHOST_kWindowState8Normal ) { - if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal; - else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized; - else if(state == GHOST_kWindowState8Minimized) state= GHOST_kWindowStateMinimized; - else if(state == GHOST_kWindowState8FullScreen) state= GHOST_kWindowStateFullScreen; - - // state = state - 8; this was the simple version of above code, doesnt work in gcc 4.0 - - setMac_windowState(1); - } else - setMac_windowState(0); - - if (state != GHOST_kWindowStateFullScreen) { - Rect bnds = { top, left, top+height, left+width }; - // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/ - gen2mac(title, title255); - - err = ::CreateNewWindow( kDocumentWindowClass, - kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute, - &bnds, - &m_windowRef); - - if ( err != noErr) { - fprintf(stderr," error creating window %i \n",(int)err); - } else { - - ::SetWRefCon(m_windowRef,(SInt32)this); - setTitle(title); - err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL); - if ( err != noErr) { - fprintf(stderr," error creating handler %i \n",(int)err); - } else { - // ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL); - ::ShowWindow(m_windowRef); - ::MoveWindow (m_windowRef, left, top,true); - - } - } - if (m_windowRef) { - m_grafPtr = ::GetWindowPort(m_windowRef); - setDrawingContextType(type); - updateDrawingContext(); - activateDrawingContext(); - } - if(ugly_hack==NULL) { - ugly_hack= m_windowRef; - // when started from commandline, window remains in the back... also for play anim - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcess(&psn); - } - } - else { - /* - Rect bnds = { top, left, top+height, left+width }; - gen2mac("", title255); - m_windowRef = ::NewCWindow( - nil, // Storage - &bnds, // Bounding rectangle of the window - title255, // Title of the window - 0, // Window initially visible - plainDBox, // procID - (WindowRef)-1L, // Put window before all other windows - 0, // Window has minimize box - (SInt32)this); // Store a pointer to the class in the refCon - */ - //GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n"); - setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL); - updateDrawingContext(); - activateDrawingContext(); - - m_tablet.Active = GHOST_kTabletModeNone; - } -} - - -GHOST_WindowCarbon::~GHOST_WindowCarbon() -{ - if (m_customCursor) delete m_customCursor; - - if(ugly_hack==m_windowRef) ugly_hack= NULL; - - // printf("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n"); - if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone); - if (m_windowRef) { - ::DisposeWindow(m_windowRef); - m_windowRef = 0; - } -} - -bool GHOST_WindowCarbon::getValid() const -{ - bool valid; - if (!m_fullScreen) { - valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef); - } - else { - valid = true; - } - return valid; -} - - -void GHOST_WindowCarbon::setTitle(const STR_String& title) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setTitle(): window invalid") - Str255 title255; - gen2mac(title, title255); - ::SetWTitle(m_windowRef, title255); -} - - -void GHOST_WindowCarbon::getTitle(STR_String& title) const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getTitle(): window invalid") - Str255 title255; - ::GetWTitle(m_windowRef, title255); - mac2gen(title255, title); -} - - -void GHOST_WindowCarbon::getWindowBounds(GHOST_Rect& bounds) const -{ - OSStatus success; - Rect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getWindowBounds(): window invalid") - success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect); - bounds.m_b = rect.bottom; - bounds.m_l = rect.left; - bounds.m_r = rect.right; - bounds.m_t = rect.top; -} - - -void GHOST_WindowCarbon::getClientBounds(GHOST_Rect& bounds) const -{ - Rect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getClientBounds(): window invalid") - //::GetPortBounds(m_grafPtr, &rect); - ::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect); - - bounds.m_b = rect.bottom; - bounds.m_l = rect.left; - bounds.m_r = rect.right; - bounds.m_t = rect.top; - - // Subtract gutter height from bottom -#ifdef GHOST_DRAW_CARBON_GUTTER - if ((bounds.m_b - bounds.m_t) > s_sizeRectSize) - { - bounds.m_b -= s_sizeRectSize; - } - else - { - bounds.m_t = bounds.m_b; - } -#endif //GHOST_DRAW_CARBON_GUTTER -} - - -GHOST_TSuccess GHOST_WindowCarbon::setClientWidth(GHOST_TUns32 width) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientWidth(): window invalid") - GHOST_Rect cBnds, wBnds; - getClientBounds(cBnds); - if (((GHOST_TUns32)cBnds.getWidth()) != width) { - ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true); - } - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setClientHeight(GHOST_TUns32 height) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientHeight(): window invalid") - GHOST_Rect cBnds, wBnds; - getClientBounds(cBnds); -#ifdef GHOST_DRAW_CARBON_GUTTER - if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) { - ::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true); - } -#else //GHOST_DRAW_CARBON_GUTTER - if (((GHOST_TUns32)cBnds.getHeight()) != height) { - ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true); - } -#endif //GHOST_DRAW_CARBON_GUTTER - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientSize(): window invalid") - GHOST_Rect cBnds, wBnds; - getClientBounds(cBnds); -#ifdef GHOST_DRAW_CARBON_GUTTER - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) { - ::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true); - } -#else //GHOST_DRAW_CARBON_GUTTER - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height)) { - ::SizeWindow(m_windowRef, width, height, true); - } -#endif //GHOST_DRAW_CARBON_GUTTER - return GHOST_kSuccess; -} - - -GHOST_TWindowState GHOST_WindowCarbon::getState() const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getState(): window invalid") - GHOST_TWindowState state; - if (::IsWindowVisible(m_windowRef) == false) { - state = GHOST_kWindowStateMinimized; - } - else if (::IsWindowInStandardState(m_windowRef, nil, nil)) { - state = GHOST_kWindowStateMaximized; - } - else { - state = GHOST_kWindowStateNormal; - } - return state; -} - - -void GHOST_WindowCarbon::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::screenToClient(): window invalid") - Point point; - point.h = inX; - point.v = inY; - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(m_grafPtr); - ::GlobalToLocal(&point); - ::SetPort(oldPort); - outX = point.h; - outY = point.v; -} - - -void GHOST_WindowCarbon::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::clientToScreen(): window invalid") - Point point; - point.h = inX; - point.v = inY; - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(m_grafPtr); - ::LocalToGlobal(&point); - ::SetPort(oldPort); - outX = point.h; - outY = point.v; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setState(GHOST_TWindowState state) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setState(): window invalid") - switch (state) { - case GHOST_kWindowStateMinimized: - ::HideWindow(m_windowRef); - break; - case GHOST_kWindowStateModified: - SetWindowModified(m_windowRef, 1); - break; - case GHOST_kWindowStateUnModified: - SetWindowModified(m_windowRef, 0); - break; - case GHOST_kWindowStateMaximized: - case GHOST_kWindowStateNormal: - default: - ::ShowWindow(m_windowRef); - break; - } - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setOrder(GHOST_TWindowOrder order) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setOrder(): window invalid") - if (order == GHOST_kWindowOrderTop) { - //::BringToFront(m_windowRef); is wrong, front window should be active for input too - ::SelectWindow(m_windowRef); - } - else { - /* doesnt work if you do this with a mouseclick */ - ::SendBehind(m_windowRef, nil); - } - return GHOST_kSuccess; -} - -/*#define WAIT_FOR_VSYNC 1*/ -#ifdef WAIT_FOR_VSYNC -#include -#endif - -GHOST_TSuccess GHOST_WindowCarbon::swapBuffers() -{ -#ifdef WAIT_FOR_VSYNC -/* wait for vsync, to avoid tearing artifacts */ -long VBL = 1; -CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL); -#endif - - GHOST_TSuccess succeeded = GHOST_kSuccess; - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglSwapBuffers(m_aglCtx); - } - else { - succeeded = GHOST_kFailure; - } - } - return succeeded; -} - -GHOST_TSuccess GHOST_WindowCarbon::updateDrawingContext() -{ - GHOST_TSuccess succeeded = GHOST_kSuccess; - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglUpdateContext(m_aglCtx); - } - else { - succeeded = GHOST_kFailure; - } - } - return succeeded; -} - -GHOST_TSuccess GHOST_WindowCarbon::activateDrawingContext() -{ - GHOST_TSuccess succeeded = GHOST_kSuccess; - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglSetCurrentContext(m_aglCtx); -#ifdef GHOST_DRAW_CARBON_GUTTER - // Restrict drawing to non-gutter area - ::aglEnable(m_aglCtx, AGL_BUFFER_RECT); - GHOST_Rect bnds; - getClientBounds(bnds); - GLint b[4] = - { - bnds.m_l, - bnds.m_t+s_sizeRectSize, - bnds.m_r-bnds.m_l, - bnds.m_b-bnds.m_t - }; - GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b); -#endif //GHOST_DRAW_CARBON_GUTTER - } - else { - succeeded = GHOST_kFailure; - } - } - return succeeded; -} - - -GHOST_TSuccess GHOST_WindowCarbon::installDrawingContext(GHOST_TDrawingContextType type) -{ - GHOST_TSuccess success = GHOST_kFailure; - switch (type) { - case GHOST_kDrawingContextTypeOpenGL: - { - if (!getValid()) break; - - AGLPixelFormat pixelFormat; - if (!m_fullScreen) { - pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow); - m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx); - if (!m_aglCtx) break; - if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx; - success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - } - else { - //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL\n"); -GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,sPreferredFormatFullScreen); - m_aglCtx = ::aglCreateContext(pixelFormat, 0); - if (!m_aglCtx) break; - if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx; - //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): created OpenGL context\n"); - //::CGGetActiveDisplayList(0, NULL, &m_numDisplays) - success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - /* - if (success == GHOST_kSuccess) { - GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL succeeded\n"); - } - else { - GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL failed\n"); - } - */ - } - ::aglDestroyPixelFormat(pixelFormat); - } - break; - - case GHOST_kDrawingContextTypeNone: - success = GHOST_kSuccess; - break; - - default: - break; - } - return success; -} - - -GHOST_TSuccess GHOST_WindowCarbon::removeDrawingContext() -{ - GHOST_TSuccess success = GHOST_kFailure; - switch (m_drawingContextType) { - case GHOST_kDrawingContextTypeOpenGL: - if (m_aglCtx) { - aglSetCurrentContext(NULL); - aglSetDrawable(m_aglCtx, NULL); - //aglDestroyContext(m_aglCtx); - if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL; - success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - m_aglCtx = 0; - } - break; - case GHOST_kDrawingContextTypeNone: - success = GHOST_kSuccess; - break; - default: - break; - } - return success; -} - - -GHOST_TSuccess GHOST_WindowCarbon::invalidate() -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::invalidate(): window invalid") - if (!m_fullScreen) { - Rect rect; - ::GetPortBounds(m_grafPtr, &rect); - ::InvalWindowRect(m_windowRef, &rect); - } - else { - //EventRef event; - //OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event); - //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): created event " << status << " \n"); - //status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this); - //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): set event parameter " << status << " \n"); - //status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard); - //status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget()); - //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): added event to queue " << status << " \n"); - m_fullScreenDirty = true; - } - return GHOST_kSuccess; -} - - -void GHOST_WindowCarbon::gen2mac(const STR_String& in, Str255 out) const -{ - STR_String tempStr = in; - int num = tempStr.Length(); - if (num > 255) num = 255; - ::memcpy(out+1, tempStr.Ptr(), num); - out[0] = num; -} - - -void GHOST_WindowCarbon::mac2gen(const Str255 in, STR_String& out) const -{ - char tmp[256]; - ::memcpy(tmp, in+1, in[0]); - tmp[in[0]] = '\0'; - out = tmp; -} - -void GHOST_WindowCarbon::loadCursor(bool visible, GHOST_TStandardCursor cursor) const -{ - static bool systemCursorVisible = true; - - if (visible != systemCursorVisible) { - if (visible) { - ::ShowCursor(); - systemCursorVisible = true; - } - else { - ::HideCursor(); - systemCursorVisible = false; - } - } - - if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { - ::SetCursor( m_customCursor ); - } else { - int carbon_cursor; - -#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break - switch (cursor) { - default: - GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorRightArrow, kThemeAliasArrowCursor); - GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor); - GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor); - GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor); - GCMAP( GHOST_kStandardCursorUpDown, kThemeClosedHandCursor); - GCMAP( GHOST_kStandardCursorLeftRight, kThemeClosedHandCursor); - GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor); - GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor); - GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorCopy, kThemeCopyArrowCursor); - }; -#undef GCMAP - - ::SetThemeCursor(carbon_cursor); - } -} - - -bool GHOST_WindowCarbon::getFullScreenDirty() -{ - return m_fullScreen && m_fullScreenDirty; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorVisibility(bool visible) -{ - if (::FrontWindow() == m_windowRef) { - loadCursor(visible, getCursorShape()); - } - - return GHOST_kSuccess; -} - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorShape(GHOST_TStandardCursor shape) -{ - if (m_customCursor) { - delete m_customCursor; - m_customCursor = 0; - } - - if (::FrontWindow() == m_windowRef) { - loadCursor(getCursorVisibility(), shape); - } - - return GHOST_kSuccess; -} - -#if 0 -/** Reverse the bits in a GHOST_TUns8 */ -static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) -{ - ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA); - ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC); - ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0); - return ch; -} -#endif - - -/** Reverse the bits in a GHOST_TUns16 */ -static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) -{ - shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA); - shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC); - shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0); - shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00); - return shrt; -} - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) -{ - int y; - - if (m_customCursor) { - delete m_customCursor; - m_customCursor = 0; - } - - m_customCursor = new Cursor; - if (!m_customCursor) return GHOST_kFailure; - - for (y=0; y<16; y++) { -#if !defined(__LITTLE_ENDIAN__) - m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8)); - m_customCursor->mask[y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8)); -#else - m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8)); - m_customCursor->mask[y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8)); -#endif - - } - - m_customCursor->hotSpot.h = hotX; - m_customCursor->hotSpot.v = hotY; - - if (::FrontWindow() == m_windowRef) { - loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); - } - - return GHOST_kSuccess; -} - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], - GHOST_TUns8 mask[16][2], int hotX, int hotY) -{ - return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1); -} - - -void GHOST_WindowCarbon::setMac_windowState(short value) -{ - mac_windowState = value; -} - -short GHOST_WindowCarbon::getMac_windowState() -{ - return mac_windowState; -} diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h deleted file mode 100644 index 16d79b604dd..00000000000 --- a/intern/ghost/intern/GHOST_WindowCarbon.h +++ /dev/null @@ -1,312 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** - * @file GHOST_WindowCarbon.h - * Declaration of GHOST_WindowCarbon class. - */ - -#ifndef _GHOST_WINDOW_CARBON_H_ -#define _GHOST_WINDOW_CARBON_H_ - -#ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ - -#include "GHOST_Window.h" -#include "STR_String.h" - -#define __CARBONSOUND__ -#include - -#include - - -/** - * Window on Mac OSX/Carbon. - * Carbon windows have a size widget in the lower right corner of the window. - * To force it to be visible, the height of the client rectangle is reduced so - * that applications do not draw in that area. GHOST will manage that area - * which is called the gutter. - * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent - * OpenGL drawing outside the reduced client rectangle. - * @author Maarten Gribnau - * @date May 23, 2001 - */ -class GHOST_WindowCarbon : public GHOST_Window { -public: - /** - * Constructor. - * Creates a new window and opens it. - * To check if the window was created properly, use the getValid() method. - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - */ - GHOST_WindowCarbon( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false, - const GHOST_TUns16 numOfAASamples = 0 - ); - - /** - * Destructor. - * Closes the window and disposes resources allocated. - */ - virtual ~GHOST_WindowCarbon(); - - /** - * Returns indication as to whether the window is valid. - * @return The validity of the window. - */ - virtual bool getValid() const; - - /** - * Sets the title displayed in the title bar. - * @param title The title to display in the title bar. - */ - virtual void setTitle(const STR_String& title); - - /** - * Returns the title displayed in the title bar. - * @param title The title displayed in the title bar. - */ - virtual void getTitle(STR_String& title) const; - - /** - * Returns the window rectangle dimensions. - * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. - * @param bounds The bounding rectangle of the window. - */ - virtual void getWindowBounds(GHOST_Rect& bounds) const; - - /** - * Returns the client rectangle dimensions. - * The left and top members of the rectangle are always zero. - * @param bounds The bounding rectangle of the cleient area of the window. - */ - virtual void getClientBounds(GHOST_Rect& bounds) const; - - /** - * Resizes client rectangle width. - * @param width The new width of the client area of the window. - */ - virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); - - /** - * Resizes client rectangle height. - * @param height The new height of the client area of the window. - */ - virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); - - /** - * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. - */ - virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); - - /** - * Returns the state of the window (normal, minimized, maximized). - * @return The state of the window. - */ - virtual GHOST_TWindowState getState() const; - - /** - * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. - */ - virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; - - /** - * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. - */ - virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; - - /** - * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. - */ - virtual GHOST_TSuccess setState(GHOST_TWindowState state); - - /** - * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. - */ - virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); - - /** - * Swaps front and back buffers of a window. - * @return A boolean success indicator. - */ - virtual GHOST_TSuccess swapBuffers(); - - /** - * Updates the drawing context of this window. Needed - * whenever the window is changed. - * @return Indication of success. - */ - GHOST_TSuccess updateDrawingContext(); - - /** - * Activates the drawing context of this window. - * @return A boolean success indicator. - */ - virtual GHOST_TSuccess activateDrawingContext(); - - virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; - - /** - * Returns the dirty state of the window when in full-screen mode. - * @return Whether it is dirty. - */ - virtual bool getFullScreenDirty(); - - /* accessor for fullscreen window */ - virtual void setMac_windowState(short value); - virtual short getMac_windowState(); - - - const GHOST_TabletData* GetTabletData() - { return &m_tablet; } - - GHOST_TabletData& GetCarbonTabletData() - { return m_tablet; } -protected: - /** - * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. - */ - virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); - - /** - * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. - */ - virtual GHOST_TSuccess removeDrawingContext(); - - /** - * Invalidates the contents of this window. - * @return Indication of success. - */ - virtual GHOST_TSuccess invalidate(); - - /** - * Sets the cursor visibility on the window using - * native window system calls. - */ - virtual GHOST_TSuccess setWindowCursorVisibility(bool visible); - - /** - * Sets the cursor shape on the window using - * native window system calls. - */ - virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); - - /** - * Sets the cursor shape on the window using - * native window system calls. - */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color); - - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); - - /** - * Converts a string object to a Mac Pascal string. - * @param in The string object to be converted. - * @param out The converted string. - */ - virtual void gen2mac(const STR_String& in, Str255 out) const; - - /** - * Converts a Mac Pascal string to a string object. - * @param in The string to be converted. - * @param out The converted string object. - */ - virtual void mac2gen(const Str255 in, STR_String& out) const; - - WindowRef m_windowRef; - CGrafPtr m_grafPtr; - AGLContext m_aglCtx; - - /** The first created OpenGL context (for sharing display lists) */ - static AGLContext s_firstaglCtx; - - Cursor* m_customCursor; - - GHOST_TabletData m_tablet; - - /** When running in full-screen this tells whether to refresh the window. */ - bool m_fullScreenDirty; - - /** specific MacOs X full screen window setting as we use partially system mechanism - values : 0 not maximizable default - 1 normal state - 2 maximized state - - this will be reworked when rebuilding GHOST carbon to use new OS X apis - in order to be unified with GHOST fullscreen/maximised settings - - (lukep) - **/ - - short mac_windowState; - - - /** - * The width/height of the size rectangle in the lower right corner of a - * Mac/Carbon window. This is also the height of the gutter area. - */ -#ifdef GHOST_DRAW_CARBON_GUTTER - static const GHOST_TInt32 s_sizeRectSize; -#endif // GHOST_DRAW_CARBON_GUTTER -}; - -#endif // _GHOST_WINDOW_CARBON_H_ - -- cgit v1.2.3 From 8a4d43427d70f5099c1a472f6f816b16d6576508 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:10:57 +0000 Subject: removed more unused Macintosh Carbon code --- intern/ghost/intern/GHOST_SystemCarbon.cpp | 1236 ---------------------------- intern/ghost/intern/GHOST_SystemCarbon.h | 298 ------- 2 files changed, 1534 deletions(-) delete mode 100644 intern/ghost/intern/GHOST_SystemCarbon.cpp delete mode 100644 intern/ghost/intern/GHOST_SystemCarbon.h (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp deleted file mode 100644 index 5522a0736c4..00000000000 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ /dev/null @@ -1,1236 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** - - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 7, 2001 - */ - -#include -#include -#include "GHOST_SystemCarbon.h" - -#include "GHOST_DisplayManagerCarbon.h" -#include "GHOST_EventKey.h" -#include "GHOST_EventButton.h" -#include "GHOST_EventCursor.h" -#include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" - -#include "GHOST_TimerManager.h" -#include "GHOST_TimerTask.h" -#include "GHOST_WindowManager.h" -#include "GHOST_WindowCarbon.h" -#include "GHOST_NDOFManager.h" -#include "AssertMacros.h" - -#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; } - -/* blender class and types events */ -enum { - kEventClassBlender = 'blnd' -}; - -enum { - kEventBlenderNdofAxis = 1, - kEventBlenderNdofButtons = 2 -}; - -const EventTypeSpec kEvents[] = -{ - { kEventClassAppleEvent, kEventAppleEvent }, -/* - { kEventClassApplication, kEventAppActivated }, - { kEventClassApplication, kEventAppDeactivated }, -*/ - { kEventClassKeyboard, kEventRawKeyDown }, - { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - - { kEventClassWindow, kEventWindowClickZoomRgn } , /* for new zoom behaviour */ - { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */ - { kEventClassWindow, kEventWindowExpand } , /* for new zoom behaviour */ - { kEventClassWindow, kEventWindowExpandAll }, /* for new zoom behaviour */ - - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowUpdate }, - { kEventClassWindow, kEventWindowBoundsChanged }, - - { kEventClassBlender, kEventBlenderNdofAxis }, - { kEventClassBlender, kEventBlenderNdofButtons } - - - -}; - - - -static GHOST_TButtonMask convertButton(EventMouseButton button) -{ - switch (button) { - case kEventMouseButtonPrimary: - return GHOST_kButtonMaskLeft; - case kEventMouseButtonSecondary: - return GHOST_kButtonMaskRight; - case kEventMouseButtonTertiary: - default: - return GHOST_kButtonMaskMiddle; - } -} - -static GHOST_TKey convertKey(int rawCode) -{ - /* This bit of magic converts the rawCode into a virtual - * Mac key based on the current keyboard mapping, but - * without regard to the modifiers (so we don't get 'a' - * and 'A' for example. - */ - static UInt32 dummy= 0; - Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache); - unsigned char vk = KeyTranslate(transData, rawCode, &dummy); - /* Map numpad based on rawcodes first, otherwise they - * look like non-numpad events. - * Added too: mapping the number keys, for french keyboards etc (ton) - */ - // printf("GHOST: vk: %d %c raw: %d\n", vk, vk, rawCode); - - switch (rawCode) { - case 18: return GHOST_kKey1; - case 19: return GHOST_kKey2; - case 20: return GHOST_kKey3; - case 21: return GHOST_kKey4; - case 23: return GHOST_kKey5; - case 22: return GHOST_kKey6; - case 26: return GHOST_kKey7; - case 28: return GHOST_kKey8; - case 25: return GHOST_kKey9; - case 29: return GHOST_kKey0; - - case 82: return GHOST_kKeyNumpad0; - case 83: return GHOST_kKeyNumpad1; - case 84: return GHOST_kKeyNumpad2; - case 85: return GHOST_kKeyNumpad3; - case 86: return GHOST_kKeyNumpad4; - case 87: return GHOST_kKeyNumpad5; - case 88: return GHOST_kKeyNumpad6; - case 89: return GHOST_kKeyNumpad7; - case 91: return GHOST_kKeyNumpad8; - case 92: return GHOST_kKeyNumpad9; - case 65: return GHOST_kKeyNumpadPeriod; - case 76: return GHOST_kKeyNumpadEnter; - case 69: return GHOST_kKeyNumpadPlus; - case 78: return GHOST_kKeyNumpadMinus; - case 67: return GHOST_kKeyNumpadAsterisk; - case 75: return GHOST_kKeyNumpadSlash; - } - - if ((vk >= 'a') && (vk <= 'z')) { - return (GHOST_TKey) (vk - 'a' + GHOST_kKeyA); - } else if ((vk >= '0') && (vk <= '9')) { - return (GHOST_TKey) (vk - '0' + GHOST_kKey0); - } else if (vk==16) { - switch (rawCode) { - case 122: return GHOST_kKeyF1; - case 120: return GHOST_kKeyF2; - case 99: return GHOST_kKeyF3; - case 118: return GHOST_kKeyF4; - case 96: return GHOST_kKeyF5; - case 97: return GHOST_kKeyF6; - case 98: return GHOST_kKeyF7; - case 100: return GHOST_kKeyF8; - case 101: return GHOST_kKeyF9; - case 109: return GHOST_kKeyF10; - case 103: return GHOST_kKeyF11; - case 111: return GHOST_kKeyF12; // Never get, is used for ejecting the CD! - } - } else { - switch (vk) { - case kUpArrowCharCode: return GHOST_kKeyUpArrow; - case kDownArrowCharCode: return GHOST_kKeyDownArrow; - case kLeftArrowCharCode: return GHOST_kKeyLeftArrow; - case kRightArrowCharCode: return GHOST_kKeyRightArrow; - - case kReturnCharCode: return GHOST_kKeyEnter; - case kBackspaceCharCode: return GHOST_kKeyBackSpace; - case kDeleteCharCode: return GHOST_kKeyDelete; - case kEscapeCharCode: return GHOST_kKeyEsc; - case kTabCharCode: return GHOST_kKeyTab; - case kSpaceCharCode: return GHOST_kKeySpace; - - case kHomeCharCode: return GHOST_kKeyHome; - case kEndCharCode: return GHOST_kKeyEnd; - case kPageUpCharCode: return GHOST_kKeyUpPage; - case kPageDownCharCode: return GHOST_kKeyDownPage; - - case '-': return GHOST_kKeyMinus; - case '=': return GHOST_kKeyEqual; - case ',': return GHOST_kKeyComma; - case '.': return GHOST_kKeyPeriod; - case '/': return GHOST_kKeySlash; - case ';': return GHOST_kKeySemicolon; - case '\'': return GHOST_kKeyQuote; - case '\\': return GHOST_kKeyBackslash; - case '[': return GHOST_kKeyLeftBracket; - case ']': return GHOST_kKeyRightBracket; - case '`': return GHOST_kKeyAccentGrave; - } - } - - // printf("GHOST: unknown key: %d %d\n", vk, rawCode); - - return GHOST_kKeyUnknown; -} - -/* MacOSX returns a Roman charset with kEventParamKeyMacCharCodes - * as defined here: http://developer.apple.com/documentation/mac/Text/Text-516.html - * I am not sure how international this works... - * For cross-platform convention, we'll use the Latin ascii set instead. - * As defined at: http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html - * - */ -static unsigned char convertRomanToLatin(unsigned char ascii) -{ - - if(ascii<128) return ascii; - - switch(ascii) { - case 128: return 142; - case 129: return 143; - case 130: return 128; - case 131: return 201; - case 132: return 209; - case 133: return 214; - case 134: return 220; - case 135: return 225; - case 136: return 224; - case 137: return 226; - case 138: return 228; - case 139: return 227; - case 140: return 229; - case 141: return 231; - case 142: return 233; - case 143: return 232; - case 144: return 234; - case 145: return 235; - case 146: return 237; - case 147: return 236; - case 148: return 238; - case 149: return 239; - case 150: return 241; - case 151: return 243; - case 152: return 242; - case 153: return 244; - case 154: return 246; - case 155: return 245; - case 156: return 250; - case 157: return 249; - case 158: return 251; - case 159: return 252; - case 160: return 0; - case 161: return 176; - case 162: return 162; - case 163: return 163; - case 164: return 167; - case 165: return 183; - case 166: return 182; - case 167: return 223; - case 168: return 174; - case 169: return 169; - case 170: return 174; - case 171: return 180; - case 172: return 168; - case 173: return 0; - case 174: return 198; - case 175: return 216; - case 176: return 0; - case 177: return 177; - case 178: return 0; - case 179: return 0; - case 180: return 165; - case 181: return 181; - case 182: return 0; - case 183: return 0; - case 184: return 215; - case 185: return 0; - case 186: return 0; - case 187: return 170; - case 188: return 186; - case 189: return 0; - case 190: return 230; - case 191: return 248; - case 192: return 191; - case 193: return 161; - case 194: return 172; - case 195: return 0; - case 196: return 0; - case 197: return 0; - case 198: return 0; - case 199: return 171; - case 200: return 187; - case 201: return 201; - case 202: return 0; - case 203: return 192; - case 204: return 195; - case 205: return 213; - case 206: return 0; - case 207: return 0; - case 208: return 0; - case 209: return 0; - case 210: return 0; - - case 214: return 247; - - case 229: return 194; - case 230: return 202; - case 231: return 193; - case 232: return 203; - case 233: return 200; - case 234: return 205; - case 235: return 206; - case 236: return 207; - case 237: return 204; - case 238: return 211; - case 239: return 212; - case 240: return 0; - case 241: return 210; - case 242: return 218; - case 243: return 219; - case 244: return 217; - case 245: return 0; - case 246: return 0; - case 247: return 0; - case 248: return 0; - case 249: return 0; - case 250: return 0; - - - default: return 0; - } - -} - - -/***/ - -GHOST_SystemCarbon::GHOST_SystemCarbon() : - m_modifierMask(0) -{ - m_displayManager = new GHOST_DisplayManagerCarbon (); - GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n"); - m_displayManager->initialize(); - - UnsignedWide micros; - ::Microseconds(µs); - m_start_time = UnsignedWideToUInt64(micros)/1000; - m_ignoreWindowSizedMessages = false; -} - -GHOST_SystemCarbon::~GHOST_SystemCarbon() -{ -} - - -GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const -{ - UnsignedWide micros; - ::Microseconds(µs); - UInt64 millis; - millis = UnsignedWideToUInt64(micros); - return (millis / 1000) - m_start_time; -} - - -GHOST_TUns8 GHOST_SystemCarbon::getNumDisplays() const -{ - // We do not support multiple monitors at the moment - return 1; -} - - -void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const -{ - BitMap screenBits; - Rect bnds = GetQDGlobalsScreenBits(&screenBits)->bounds; - width = bnds.right - bnds.left; - height = bnds.bottom - bnds.top; -} - - -GHOST_IWindow* GHOST_SystemCarbon::createWindow( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - bool stereoVisual, - const GHOST_TUns16 numOfAASamples, - const GHOST_TEmbedderWindowID parentWindow -) -{ - GHOST_IWindow* window = 0; - - window = new GHOST_WindowCarbon (title, left, top, width, height, state, type); - - if (window) { - if (window->getValid()) { - // Store the pointer to the window - GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); - m_windowManager->addWindow(window); - m_windowManager->setActiveWindow(window); - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); - } - else { - GHOST_PRINT("GHOST_SystemCarbon::createWindow(): window invalid\n"); - delete window; - window = 0; - } - } - else { - GHOST_PRINT("GHOST_SystemCarbon::createWindow(): could not create window\n"); - } - return window; -} - -GHOST_TSuccess GHOST_SystemCarbon::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual) -{ - GHOST_TSuccess success = GHOST_kFailure; - - // need yo make this Carbon all on 10.5 for fullscreen to work correctly - CGCaptureAllDisplays(); - - success = GHOST_System::beginFullScreen( setting, window, stereoVisual); - - if( success != GHOST_kSuccess ) { - // fullscreen failed for other reasons, release - CGReleaseAllDisplays(); - } - - return success; -} - -GHOST_TSuccess GHOST_SystemCarbon::endFullScreen(void) -{ - CGReleaseAllDisplays(); - return GHOST_System::endFullScreen(); -} - -/* this is an old style low level event queue. - As we want to handle our own timers, this is ok. - the full screen hack should be removed */ -bool GHOST_SystemCarbon::processEvents(bool waitForEvent) -{ - bool anyProcessed = false; - EventRef event; - -// SetMouseCoalescingEnabled(false, NULL); - - do { - GHOST_TimerManager* timerMgr = getTimerManager(); - - if (waitForEvent) { - GHOST_TUns64 next = timerMgr->nextFireTime(); - double timeOut; - - if (next == GHOST_kFireTimeNever) { - timeOut = kEventDurationForever; - } else { - timeOut = (double)(next - getMilliSeconds())/1000.0; - if (timeOut < 0.0) - timeOut = 0.0; - } - - ::ReceiveNextEvent(0, NULL, timeOut, false, &event); - } - - if (timerMgr->fireTimers(getMilliSeconds())) { - anyProcessed = true; - } - - if (getFullScreen()) { - // Check if the full-screen window is dirty - GHOST_IWindow* window = m_windowManager->getFullScreenWindow(); - if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) { - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); - anyProcessed = true; - } - } - - /* end loop when no more events available */ - while (::ReceiveNextEvent(0, NULL, 0, true, &event)==noErr) { - OSStatus status= ::SendEventToEventTarget(event, ::GetEventDispatcherTarget()); - if (status==noErr) { - anyProcessed = true; - } else { - UInt32 i= ::GetEventClass(event); - - /* Ignore 'cgs ' class, no documentation on what they - * are, but we get a lot of them - */ - if (i!='cgs ') { - if (i!='tblt') { // tablet event. we use the one packaged in the mouse event - ; //printf("Missed - Class: '%.4s', Kind: %d\n", &i, ::GetEventKind(event)); - } - } - } - ::ReleaseEvent(event); - } - } while (waitForEvent && !anyProcessed); - - return anyProcessed; -} - - -GHOST_TSuccess GHOST_SystemCarbon::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const -{ - Point mouseLoc; - // Get the position of the mouse in the active port - ::GetGlobalMouse(&mouseLoc); - // Convert the coordinates to screen coordinates - x = (GHOST_TInt32)mouseLoc.h; - y = (GHOST_TInt32)mouseLoc.v; - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_SystemCarbon::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) -{ - float xf=(float)x, yf=(float)y; - - CGAssociateMouseAndMouseCursorPosition(false); - CGSetLocalEventsSuppressionInterval(0); - CGWarpMouseCursorPosition(CGPointMake(xf, yf)); - CGAssociateMouseAndMouseCursorPosition(true); - -//this doesn't work properly, see game engine mouse-look scripts -// CGWarpMouseCursorPosition(CGPointMake(xf, yf)); - // this call below sends event, but empties other events (like shift) - // CGPostMouseEvent(CGPointMake(xf, yf), TRUE, 1, FALSE, 0); - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const -{ - UInt32 modifiers = ::GetCurrentKeyModifiers(); - - keys.set(GHOST_kModifierKeyCommand, (modifiers & cmdKey) ? true : false); - keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & optionKey) ? true : false); - keys.set(GHOST_kModifierKeyLeftShift, (modifiers & shiftKey) ? true : false); - keys.set(GHOST_kModifierKeyLeftControl, (modifiers & controlKey) ? true : false); - - return GHOST_kSuccess; -} - - /* XXX, incorrect for multibutton mice */ -GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const -{ - Boolean theOnlyButtonIsDown = ::Button(); - buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, theOnlyButtonIsDown); - return GHOST_kSuccess; -} - -#define FIRSTFILEBUFLG 512 -static bool g_hasFirstFile = false; -static char g_firstFileBuf[512]; - -extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { - if (g_hasFirstFile) { - strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1); - buf[FIRSTFILEBUFLG - 1] = '\0'; - return 1; - } else { - return 0; - } -} - -OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) -{ - //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; - - return noErr; -} - -OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) -{ - //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; - AEDescList docs; - SInt32 ndocs; - OSErr err; - - err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs); - if (err != noErr) return err; - - err = AECountItems(&docs, &ndocs); - if (err==noErr) { - int i; - - for (i=0; ipushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) ); - - return noErr; -} - - -GHOST_TSuccess GHOST_SystemCarbon::init() -{ - - GHOST_TSuccess success = GHOST_System::init(); - if (success) { - /* - * Initialize the cursor to the standard arrow shape (so that we can change it later on). - * This initializes the cursor's visibility counter to 0. - */ - ::InitCursor(); - - MenuRef windMenu; - ::CreateStandardWindowMenu(0, &windMenu); - ::InsertMenu(windMenu, 0); - ::DrawMenuBar(); - - ::InstallApplicationEventHandler(sEventHandlerProc, GetEventTypeCount(kEvents), kEvents, this, &m_handler); - - ::AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, sAEHandlerLaunch, (SInt32) this, false); - ::AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, sAEHandlerOpenDocs, (SInt32) this, false); - ::AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, sAEHandlerPrintDocs, (SInt32) this, false); - ::AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, sAEHandlerQuit, (SInt32) this, false); - - } - return success; -} - - -GHOST_TSuccess GHOST_SystemCarbon::exit() -{ - return GHOST_System::exit(); -} - - -OSStatus GHOST_SystemCarbon::handleWindowEvent(EventRef event) -{ - WindowRef windowRef; - GHOST_WindowCarbon *window; - OSStatus err = eventNotHandledErr; - - // Check if the event was send to a GHOST window - ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowRef); - window = (GHOST_WindowCarbon*) ::GetWRefCon(windowRef); - if (!validWindow(window)) { - return err; - } - - //if (!getFullScreen()) { - err = noErr; - switch(::GetEventKind(event)) - { - case kEventWindowClose: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); - break; - case kEventWindowActivated: - m_windowManager->setActiveWindow(window); - window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); - break; - case kEventWindowDeactivated: - m_windowManager->setWindowInactive(window); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); - break; - case kEventWindowUpdate: - //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n"); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); - break; - case kEventWindowBoundsChanged: - if (!m_ignoreWindowSizedMessages) - { - window->updateDrawingContext(); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); - } - break; - default: - err = eventNotHandledErr; - break; - } -// } - //else { - //window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow(); - //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n"); - //::RemoveEventFromQueue(::GetMainEventQueue(), event); - //} - - return err; -} - -OSStatus GHOST_SystemCarbon::handleTabletEvent(EventRef event) -{ - GHOST_IWindow* window = m_windowManager->getActiveWindow(); - TabletPointRec tabletPointRecord; - TabletProximityRec tabletProximityRecord; - UInt32 anInt32; - GHOST_TabletData& ct=((GHOST_WindowCarbon*)window)->GetCarbonTabletData(); - OSStatus err = eventNotHandledErr; - - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; - - // is there an embedded tablet event inside this mouse event? - if(noErr == GetEventParameter(event, kEventParamTabletEventType, typeUInt32, NULL, sizeof(UInt32), NULL, (void *)&anInt32)) - { - // yes there is one! - // Embedded tablet events can either be a proximity or pointer event. - if(anInt32 == kEventTabletPoint) - { - //GHOST_PRINT("Embedded pointer event!\n"); - - // Extract the tablet Pointer Event. If there is no Tablet Pointer data - // in this event, then this call will return an error. Just ignore the - // error and go on. This can occur when a proximity event is embedded in - // a mouse event and you did not check the mouse event to see which type - // of tablet event was embedded. - if(noErr == GetEventParameter(event, kEventParamTabletPointRec, - typeTabletPointRec, NULL, - sizeof(TabletPointRec), - NULL, (void *)&tabletPointRecord)) - { - ct.Pressure = tabletPointRecord.pressure / 65535.0f; - ct.Xtilt = tabletPointRecord.tiltX / 32767.0f; /* can be positive or negative */ - ct.Ytilt = tabletPointRecord.tiltY / 32767.0f; /* can be positive or negative */ - } - } else { - //GHOST_PRINT("Embedded proximity event\n"); - - // Extract the Tablet Proximity record from the event. - if(noErr == GetEventParameter(event, kEventParamTabletProximityRec, - typeTabletProximityRec, NULL, - sizeof(TabletProximityRec), - NULL, (void *)&tabletProximityRecord)) - { - if (tabletProximityRecord.enterProximity) { - //pointer is entering tablet area proximity - - switch(tabletProximityRecord.pointerType) - { - case 1: /* stylus */ - ct.Active = GHOST_kTabletModeStylus; - break; - case 2: /* puck, not supported so far */ - ct.Active = GHOST_kTabletModeNone; - break; - case 3: /* eraser */ - ct.Active = GHOST_kTabletModeEraser; - break; - default: - ct.Active = GHOST_kTabletModeNone; - break; - } - } else { - // pointer is leaving - return to mouse - ct.Active = GHOST_kTabletModeNone; - } - } - } - err = noErr; - } - return err; -} - -OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event) -{ - OSStatus err = eventNotHandledErr; - GHOST_IWindow* window = m_windowManager->getActiveWindow(); - UInt32 kind = ::GetEventKind(event); - - switch (kind) - { - case kEventMouseDown: - case kEventMouseUp: - // Handle Mac application responsibilities - if ((kind == kEventMouseDown) && handleMouseDown(event)) { - err = noErr; - } - else { - GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; - EventMouseButton button; - - /* Window still gets mouse up after command-H */ - if (m_windowManager->getActiveWindow()) { - // handle any tablet events that may have come with the mouse event (optional) - handleTabletEvent(event); - - ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button))); - err = noErr; - } - } - break; - - case kEventMouseMoved: - case kEventMouseDragged: { - Point mousePos; - - if (window) { - //handle any tablet events that may have come with the mouse event (optional) - handleTabletEvent(event); - - ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); - pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v)); - err = noErr; - } - break; - } - case kEventMouseWheelMoved: - { - OSStatus status; - //UInt32 modifiers; - EventMouseWheelAxis axis; - SInt32 delta; - //status = ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); - //GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed"); - status = ::GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis); - GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed"); - if (axis == kEventMouseWheelAxisY) - { - status = ::GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta); - GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed"); - /* - * Limit mouse wheel delta to plus and minus one. - */ - delta = delta > 0 ? 1 : -1; - pushEvent(new GHOST_EventWheel(getMilliSeconds(), window, delta)); - err = noErr; - } - } - break; - } - - return err; -} - - -OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event) -{ - OSStatus err = eventNotHandledErr; - GHOST_IWindow* window = m_windowManager->getActiveWindow(); - UInt32 kind = ::GetEventKind(event); - UInt32 modifiers; - UInt32 rawCode; - GHOST_TKey key; - unsigned char ascii; - - /* Can happen, very rarely - seems to only be when command-H makes - * the window go away and we still get an HKey up. - */ - if (!window) { - //::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode); - //key = convertKey(rawCode); - return err; - } - - err = noErr; - switch (kind) { - case kEventRawKeyDown: - case kEventRawKeyRepeat: - case kEventRawKeyUp: - ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode); - ::GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &ascii); - - key = convertKey(rawCode); - ascii= convertRomanToLatin(ascii); - - // if (key!=GHOST_kKeyUnknown) { - GHOST_TEventType type; - if (kind == kEventRawKeyDown) { - type = GHOST_kEventKeyDown; - } else if (kind == kEventRawKeyRepeat) { - type = GHOST_kEventKeyDown; /* XXX, fixme */ - } else { - type = GHOST_kEventKeyUp; - } - pushEvent( new GHOST_EventKey( getMilliSeconds(), type, window, key, ascii) ); -// } - break; - - case kEventRawKeyModifiersChanged: - /* ugh */ - ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - if ((modifiers & shiftKey) != (m_modifierMask & shiftKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & shiftKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); - } - if ((modifiers & controlKey) != (m_modifierMask & controlKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & controlKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); - } - if ((modifiers & optionKey) != (m_modifierMask & optionKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & optionKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); - } - if ((modifiers & cmdKey) != (m_modifierMask & cmdKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & cmdKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); - } - - m_modifierMask = modifiers; - break; - - default: - err = eventNotHandledErr; - break; - } - - return err; -} - - -bool GHOST_SystemCarbon::handleMouseDown(EventRef event) -{ - WindowPtr window; - short part; - BitMap screenBits; - bool handled = true; - GHOST_WindowCarbon* ghostWindow; - Point mousePos = {0 , 0}; - - ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); - - part = ::FindWindow(mousePos, &window); - ghostWindow = (GHOST_WindowCarbon*) ::GetWRefCon(window); - - switch (part) { - case inMenuBar: - handleMenuCommand(::MenuSelect(mousePos)); - break; - - case inDrag: - /* - * The DragWindow() routine creates a lot of kEventWindowBoundsChanged - * events. By setting m_ignoreWindowSizedMessages these are suppressed. - * @see GHOST_SystemCarbon::handleWindowEvent(EventRef event) - */ - /* even worse: scale window also generates a load of events, and nothing - is handled (read: client's event proc called) until you release mouse (ton) */ - - GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseDown: invalid window"); - m_ignoreWindowSizedMessages = true; - ::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds); - m_ignoreWindowSizedMessages = false; - - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, ghostWindow) ); - - break; - - case inContent: - if (window != ::FrontWindow()) { - ::SelectWindow(window); - /* - * We add a mouse down event on the newly actived window - */ - //GHOST_PRINT("GHOST_SystemCarbon::handleMouseDown(): adding mouse down event, " << ghostWindow << "\n"); - EventMouseButton button; - ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonDown, ghostWindow, convertButton(button))); - } else { - handled = false; - } - break; - - case inGoAway: - GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); - if (::TrackGoAway(window, mousePos)) - { - // todo: add option-close, because itÿs in the HIG - // if (event.modifiers & optionKey) { - // Close the clean documents, others will be confirmed one by one. - //} - // else { - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, ghostWindow)); - //} - } - break; - - case inGrow: - GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); - ::ResizeWindow(window, mousePos, NULL, NULL); - break; - - case inZoomIn: - case inZoomOut: - GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); - if (::TrackBox(window, mousePos, part)) { - int macState; - - macState = ghostWindow->getMac_windowState(); - if ( macState== 0) - ::ZoomWindow(window, part, true); - else - if (macState == 2) { // always ok - ::ZoomWindow(window, part, true); - ghostWindow->setMac_windowState(1); - } else { // need to force size again - // GHOST_TUns32 scr_x,scr_y; /*unused*/ - Rect outAvailableRect; - - ghostWindow->setMac_windowState(2); - ::GetAvailableWindowPositioningBounds ( GetMainDevice(), &outAvailableRect); - - //this->getMainDisplayDimensions(scr_x,scr_y); - ::SizeWindow (window, outAvailableRect.right-outAvailableRect.left,outAvailableRect.bottom-outAvailableRect.top-1,false); - ::MoveWindow (window, outAvailableRect.left, outAvailableRect.top,true); - } - - } - break; - - default: - handled = false; - break; - } - - return handled; -} - - -bool GHOST_SystemCarbon::handleMenuCommand(GHOST_TInt32 menuResult) -{ - short menuID; - short menuItem; - UInt32 command; - bool handled; - OSErr err; - - menuID = HiWord(menuResult); - menuItem = LoWord(menuResult); - - err = ::GetMenuItemCommandID(::GetMenuHandle(menuID), menuItem, &command); - - handled = false; - - if (err || command == 0) { - } - else { - switch(command) { - } - } - - ::HiliteMenu(0); - return handled; -} - - -OSStatus GHOST_SystemCarbon::sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) -{ - GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) userData; - OSStatus err = eventNotHandledErr; - GHOST_IWindow* window; - GHOST_TEventNDOFData data; - UInt32 kind; - - switch (::GetEventClass(event)) - { - case kEventClassAppleEvent: - EventRecord eventrec; - if (ConvertEventRefToEventRecord(event, &eventrec)) { - err = AEProcessAppleEvent(&eventrec); - } - break; - case kEventClassMouse: - err = sys->handleMouseEvent(event); - break; - case kEventClassWindow: - err = sys->handleWindowEvent(event); - break; - case kEventClassKeyboard: - err = sys->handleKeyEvent(event); - break; - case kEventClassBlender : - window = sys->m_windowManager->getActiveWindow(); - sys->m_ndofManager->GHOST_NDOFGetDatas(data); - kind = ::GetEventKind(event); - - switch (kind) - { - case 1: - sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFMotion, window, data)); - // printf("motion\n"); - break; - case 2: - sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFButton, window, data)); -// printf("button\n"); - break; - } - err = noErr; - break; - default : - ; - break; - } - - return err; -} - -GHOST_TUns8* GHOST_SystemCarbon::getClipboard(bool selection) const -{ - PasteboardRef inPasteboard; - PasteboardItemID itemID; - CFDataRef flavorData; - OSStatus err = noErr; - GHOST_TUns8 * temp_buff; - CFRange range; - OSStatus syncFlags; - - err = PasteboardCreate(kPasteboardClipboard, &inPasteboard); - if(err != noErr) { return NULL;} - - syncFlags = PasteboardSynchronize( inPasteboard ); - /* as we always get in a new string, we can safely ignore sync flags if not an error*/ - if(syncFlags <0) { return NULL;} - - - err = PasteboardGetItemIdentifier( inPasteboard, 1, &itemID ); - if(err != noErr) { return NULL;} - - err = PasteboardCopyItemFlavorData( inPasteboard, itemID, CFSTR("public.utf8-plain-text"), &flavorData); - if(err != noErr) { return NULL;} - - range = CFRangeMake(0, CFDataGetLength(flavorData)); - - temp_buff = (GHOST_TUns8*) malloc(range.length+1); - - CFDataGetBytes(flavorData, range, (UInt8*)temp_buff); - - temp_buff[range.length] = '\0'; - - if(temp_buff) { - return temp_buff; - } else { - return NULL; - } -} - -void GHOST_SystemCarbon::putClipboard(GHOST_TInt8 *buffer, bool selection) const -{ - if(selection) {return;} // for copying the selection, used on X11 - - PasteboardRef inPasteboard; - CFDataRef textData = NULL; - OSStatus err = noErr; /*For error checking*/ - OSStatus syncFlags; - - err = PasteboardCreate(kPasteboardClipboard, &inPasteboard); - if(err != noErr) { return;} - - syncFlags = PasteboardSynchronize( inPasteboard ); - /* as we always put in a new string, we can safely ignore sync flags */ - if(syncFlags <0) { return;} - - err = PasteboardClear( inPasteboard ); - if(err != noErr) { return;} - - textData = CFDataCreate(kCFAllocatorDefault, (UInt8*)buffer, strlen(buffer)); - - if (textData) { - err = PasteboardPutItemFlavor( inPasteboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), textData, 0); - if(err != noErr) { - if(textData) { CFRelease(textData);} - return; - } - } - - if(textData) { - CFRelease(textData); - } -} - -const GHOST_TUns8* GHOST_SystemCarbon::getSystemDir() const -{ - return (GHOST_TUns8*)"/Library/Application Support/Blender"; -} - -const GHOST_TUns8* GHOST_SystemCarbon::getUserDir() const -{ - static char usrPath[256] = ""; - char* env = getenv("HOME"); - - if (env) { - strncpy(usrPath, env, 245); - usrPath[245]=0; - strcat(usrPath, "/Library/Application Support/Blender"); - return (GHOST_TUns8*) usrPath; - } - else - return NULL; -} diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h deleted file mode 100644 index ebd929749b6..00000000000 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ /dev/null @@ -1,298 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** - * @file GHOST_SystemCarbon.h - * Declaration of GHOST_SystemCarbon class. - */ - -#ifndef _GHOST_SYSTEM_CARBON_H_ -#define _GHOST_SYSTEM_CARBON_H_ - -#ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ - -#define __CARBONSOUND__ -#include - -#include "GHOST_System.h" - -class GHOST_EventCursor; -class GHOST_EventKey; -class GHOST_EventWindow; - -/** - * OSX/Carbon Implementation of GHOST_System class. - * @see GHOST_System. - * @author Maarten Gribnau - * @date May 21, 2001 - */ -class GHOST_SystemCarbon : public GHOST_System { -public: - /** - * Constructor. - */ - GHOST_SystemCarbon(); - - /** - * Destructor. - */ - ~GHOST_SystemCarbon(); - - /*************************************************************************************** - ** Time(r) functionality - ***************************************************************************************/ - - /** - * Returns the system time. - * Returns the number of milliseconds since the start of the system process. - * Based on ANSI clock() routine. - * @return The number of milliseconds. - */ - virtual GHOST_TUns64 getMilliSeconds() const; - - /*************************************************************************************** - ** Display/window management functionality - ***************************************************************************************/ - - /** - * Returns the number of displays on this system. - * @return The number of displays. - */ - virtual GHOST_TUns8 getNumDisplays() const; - - /** - * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. - */ - virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; - - /** - * Create a new window. - * The new window is added to the list of windows managed. - * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). - */ - virtual GHOST_IWindow* createWindow( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - const bool stereoVisual, - const GHOST_TUns16 numOfAASamples = 0, - const GHOST_TEmbedderWindowID parentWindow = 0 - ); - - virtual GHOST_TSuccess beginFullScreen( - const GHOST_DisplaySetting& setting, - GHOST_IWindow** window, - const bool stereoVisual - ); - - virtual GHOST_TSuccess endFullScreen( void ); - - /*************************************************************************************** - ** Event management functionality - ***************************************************************************************/ - - /** - * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. - */ - virtual bool processEvents(bool waitForEvent); - - /*************************************************************************************** - ** Cursor management functionality - ***************************************************************************************/ - - /** - * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. - */ - virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; - - /** - * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. - */ - virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); - - /*************************************************************************************** - ** Access to mouse button and keyboard states. - ***************************************************************************************/ - - /** - * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. - */ - virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; - - /** - * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. - */ - virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; - - /** - * Returns Clipboard data - * @param selection Indicate which buffer to return - * @return Returns the selected buffer - */ - virtual GHOST_TUns8* getClipboard(bool selection) const; - - /** - * Puts buffer to system clipboard - * @param buffer The buffer to be copied - * @param selection Indicates which buffer to copy too, only used on X11 - */ - virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; - - /** - * Determine the base dir in which shared resources are located. It will first try to use - * "unpack and run" path, then look for properly installed path, not including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). - */ - virtual const GHOST_TUns8* getSystemDir() const; - - /** - * Determine the base dir in which user configuration is stored, not including versioning. - * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). - */ - virtual const GHOST_TUns8* getUserDir() const; - -protected: - /** - * Initializes the system. - * For now, it justs registers the window class (WNDCLASS). - * @return A success value. - */ - virtual GHOST_TSuccess init(); - - /** - * Closes the system down. - * @return A success value. - */ - virtual GHOST_TSuccess exit(); - - - /** - * Handles a tablet event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleTabletEvent(EventRef event); - /** - * Handles a mouse event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleMouseEvent(EventRef event); - - /** - * Handles a key event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleKeyEvent(EventRef event); - - /** - * Handles a window event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleWindowEvent(EventRef event); - - /** - * Handles all basic Mac application stuff for a mouse down event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - bool handleMouseDown(EventRef event); - - /** - * Handles a Mac menu command. - * @param menuResult A Mac menu/item identifier. - * @return Indication whether the event was handled. - */ - bool handleMenuCommand(GHOST_TInt32 menuResult); - - /* callback for blender generated events */ -// static OSStatus blendEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData); - - - /** - * Callback for Carbon when it has events. - */ - static OSStatus sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData); - - /** Apple Event Handlers */ - static OSErr sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - static OSErr sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - static OSErr sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - static OSErr sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - - /** - * Callback for Mac Timer tasks that expire. - * @param tmTask Pointer to the timer task that expired. - */ - //static void s_timerCallback(TMTaskPtr tmTask); - - /** Event handler reference. */ - EventHandlerRef m_handler; - - /** Start time at initialization. */ - GHOST_TUns64 m_start_time; - - /** State of the modifiers. */ - UInt32 m_modifierMask; - - /** Ignores window size messages (when window is dragged). */ - bool m_ignoreWindowSizedMessages; -}; - -#endif // _GHOST_SYSTEM_CARBON_H_ - -- cgit v1.2.3 From b86a25efba0b5bd6d73b7207d726b67603caa934 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:15:00 +0000 Subject: removed some NDOF plugin-related code --- intern/ghost/GHOST_C-api.h | 16 +--------------- intern/ghost/GHOST_ISystem.h | 15 --------------- intern/ghost/intern/GHOST_C-api.cpp | 18 +----------------- intern/ghost/intern/GHOST_System.cpp | 14 ++------------ intern/ghost/intern/GHOST_System.h | 20 -------------------- 5 files changed, 4 insertions(+), 79 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index a5fec1f101c..a80a56207e7 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -280,21 +280,7 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa * @param windowhandle The handle to the window */ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); - - -/*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - -/** -* Open N-degree of freedom devices - */ -extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, - GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - ); + /*************************************************************************************** ** Cursor management functionality diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 1760fe30b7f..6f0adeb05b7 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -295,21 +295,6 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer) = 0; - - /*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - - /** - * Starts the N-degree of freedom device manager - */ - virtual int openNDOF(GHOST_IWindow*, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - // original patch only - // GHOST_NDOFEventHandler_fp setNdofEventHandler - ) = 0; /*************************************************************************************** diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 9da20200f63..9c278f40282 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -263,22 +263,6 @@ GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle) } -int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) - //original patch only - /* GHOST_NDOFEventHandler_fp setNdofEventHandler)*/ -{ - GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; - - return system->openNDOF((GHOST_IWindow*) windowhandle, - setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen); -// original patch -// setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen, setNdofEventHandler); -} - - GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle) { @@ -701,7 +685,7 @@ GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle) return window->invalidate(); } - +// [mce] this is going away soon extern const GHOST_TabletData* GHOST_GetTabletData(GHOST_WindowHandle windowhandle) { return ((GHOST_IWindow*)windowhandle)->GetTabletData(); diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 25b55345d46..70ff5a02924 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -237,17 +237,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event) return success; } -int GHOST_System::openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - return m_ndofManager->deviceOpen(w, - setNdofLibraryInit, - setNdofLibraryShutdown, - setNdofDeviceOpen); -} - GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const { @@ -284,7 +273,8 @@ GHOST_TSuccess GHOST_System::init() m_timerManager = new GHOST_TimerManager (); m_windowManager = new GHOST_WindowManager (); m_eventManager = new GHOST_EventManager (); - m_ndofManager = new GHOST_NDOFManager(); +// m_ndofManager = new GHOST_NDOFManager(); +// Each platform now has their own NDOFManager subclass #ifdef GHOST_DEBUG if (m_eventManager) { diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 1aeb8597573..5940894ad27 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -184,26 +184,6 @@ public: virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer); - - /*************************************************************************************** - ** N-degree of freedom devcice management functionality - ***************************************************************************************/ - - /** Inherited from GHOST_ISystem - * Opens the N-degree of freedom device manager - * return 0 if device found, 1 otherwise - */ - virtual int openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - -// original patch only -// GHOST_NDOFEventHandler_fp setNdofEventHandler); - - - - /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ -- cgit v1.2.3 From f0167c6a4117df275f85ce466c2067e0eda0e0e8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:18:12 +0000 Subject: get more mouse events only when in hi-fi mode --- intern/ghost/intern/GHOST_SystemWin32.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 1b173208b18..829f0997377 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1074,8 +1074,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // if (m_input_fidelity_hint == HI_FI) // can't access hint from static function putchar('\n'); - /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); -// printf("%d more mouse points found\n", n); + + if (m_input_fidelity_hint == HI_FI) + { + /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // printf("%d more mouse points found\n", n); + } + printf(" (%d,%d)\n", mousePosX, mousePosY); event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); -- cgit v1.2.3 From 6c2dee0198fed174a55f65685d4e01752c987547 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:23:41 +0000 Subject: revamped NDOF event system for ghost, added (untested) Mac support --- intern/ghost/GHOST_Types.h | 32 +++-- intern/ghost/intern/GHOST_EventNDOF.h | 45 +++---- intern/ghost/intern/GHOST_NDOFManager.cpp | 168 ++++++++++--------------- intern/ghost/intern/GHOST_NDOFManager.h | 40 +++--- intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 111 ++++++++++++++++ intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 45 +++++++ 6 files changed, 284 insertions(+), 157 deletions(-) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp create mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.h (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 4ec8e22a960..66bfa0e469f 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -154,7 +154,8 @@ typedef enum { GHOST_kEventTrackpad, /// Trackpad event GHOST_kEventNDOFMotion, /// N degree of freedom device motion event - GHOST_kEventNDOFButton, /// N degree of freedom device button event + GHOST_kEventNDOFButtonDown,/// N degree of freedom device button events + GHOST_kEventNDOFButtonUp, GHOST_kEventKeyDown, GHOST_kEventKeyUp, @@ -432,17 +433,17 @@ typedef struct { // float dt; //} GHOST_TEventNDOFData; -typedef struct { - /** N-degree of freedom device data v2*/ - int changed; - GHOST_TUns64 client; - GHOST_TUns64 address; - GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ - GHOST_TInt16 rx, ry, rz; - GHOST_TInt16 buttons; - GHOST_TUns64 time; - GHOST_TUns64 delta; -} GHOST_TEventNDOFData; +// typedef struct { +// /** N-degree of freedom device data v2*/ +// int changed; +// GHOST_TUns64 client; +// GHOST_TUns64 address; +// GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ +// GHOST_TInt16 rx, ry, rz; +// GHOST_TInt16 buttons; +// GHOST_TUns64 time; +// GHOST_TUns64 delta; +// } GHOST_TEventNDOFData; typedef struct { /** N-degree of freedom device data v3 [GSoC 2010]*/ @@ -454,13 +455,8 @@ typedef struct { float tx, ty, tz; /** -x left, +y forward, -z up */ float rx, ry, rz; - GHOST_TInt16 buttons; -} GHOST_TEventNDOFData_3; +} GHOST_TEventNDOFData; -// [mce] consider scrapping these, in favor of built-in SpaceNav handling. -typedef int (*GHOST_NDOFLibraryInit_fp)(); -typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); -typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData); typedef struct { /** The key code. */ diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index 916fd7bbc08..c5d35126f01 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -26,32 +26,35 @@ #include "GHOST_Event.h" -/** - * N-degree of freedom device event. - */ -class GHOST_EventNDOF : public GHOST_Event + +class GHOST_EventNDOFMotion : public GHOST_Event { +protected: + GHOST_TEventNDOFData m_axisData; + public: - /** - * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param x The x-coordinate of the location the cursor was at at the time of the event. - * @param y The y-coordinate of the location the cursor was at at the time of the event. - */ - GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, - GHOST_TEventNDOFData data) - : GHOST_Event(msec, type, window) - { - m_ndofEventData = data; - m_data = &m_ndofEventData; - } + GHOST_EventNDOFMotion(GHOST_TUns64 time) + : GHOST_Event(time, GHOST_kEventNDOFMotion, NULL) +// , m_data(&m_axisData) + { + m_data = &m_axisData; + } +}; +class GHOST_EventNDOFButton : public GHOST_Event +{ protected: - /** translation & rotation from the device. */ - GHOST_TEventNDOFData m_ndofEventData; + GHOST_TUns16 m_buttonNumber; + +public: + GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_TUns16 buttonNumber, GHOST_TEventType upOrDown) + : GHOST_Event(time, upOrDown, NULL) + , m_buttonNumber(buttonNumber) +// , m_data(&m_buttonNumber) + { + m_data = &m_buttonNumber; + } }; #endif // _GHOST_EVENT_NDOF_H_ - diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 5e5f04d5bc9..787811fc69b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -20,108 +20,70 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include /* just for printf */ - #include "GHOST_NDOFManager.h" - - -// the variable is outside the class because it must be accessed from plugin -static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0}; - -#if !defined(_WIN32) && !defined(__APPLE__) -#include "GHOST_SystemX11.h" -#endif - -namespace -{ - GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0; - GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0; - GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0; -} - -GHOST_NDOFManager::GHOST_NDOFManager() -{ - m_DeviceHandle = 0; - - // discover the API from the plugin - ndofLibraryInit = 0; - ndofLibraryShutdown = 0; - ndofDeviceOpen = 0; -} - -GHOST_NDOFManager::~GHOST_NDOFManager() -{ - if (ndofLibraryShutdown) - ndofLibraryShutdown(m_DeviceHandle); - - m_DeviceHandle = 0; -} - - -int -GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - int Pid; +#include "GHOST_EventNDOF.h" + +GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) + : m_system(sys) +// , m_translation((short[]){0,0,0}) +// , m_rotation((short[]){0,0,0}) + , m_buttons(0) + , m_atRest(true) + { } + +void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) + { + memcpy(m_translation, t, sizeof(m_translation)); + m_motionTime = time; + m_atRest = false; + } + +void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) + { + memcpy(m_rotation, r, sizeof(m_rotation)); + m_motionTime = time; + m_atRest = false; + } + +void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) + { + unsigned short diff = m_buttons ^ buttons; + for (int i = 0; i < 16; ++i) + { + unsigned short mask = 1 << i; + if (diff & mask) + m_system.pushEvent(new GHOST_EventNDOFButton(time, i + 1, + (buttons & mask) ? GHOST_kEventNDOFButtonDown : GHOST_kEventNDOFButtonUp)); + } + + m_buttons = buttons; + } + +bool GHOST_NDOFManager::sendMotionEvent() + { + if (m_atRest) + return false; + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime); + GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData(); + + const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually + + // scale *= m_sensitivity; + + data->tx = scale * m_translation[0]; + data->ty = scale * m_translation[1]; + data->tz = scale * m_translation[2]; + + data->rx = scale * m_rotation[0]; + data->ry = scale * m_rotation[1]; + data->rz = scale * m_rotation[2]; + + m_system.pushEvent(event); + + // 'at rest' test goes at the end so that the first 'rest' event gets sent + m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && + m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; - ndofLibraryInit = setNdofLibraryInit; - ndofLibraryShutdown = setNdofLibraryShutdown; - ndofDeviceOpen = setNdofDeviceOpen; - - if (ndofLibraryInit && ndofDeviceOpen) - { - Pid= ndofLibraryInit(); -#if 0 - printf("%i client \n", Pid); -#endif - #if defined(_WIN32) || defined(__APPLE__) - m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues); - #else - GHOST_SystemX11 *sys; - sys = static_cast(GHOST_ISystem::getSystem()); - void *ndofInfo = sys->prepareNdofInfo(¤tNdofValues); - m_DeviceHandle = ndofDeviceOpen(ndofInfo); - #endif - return (Pid > 0) ? 0 : 1; - - } else - return 1; -} - - -bool -GHOST_NDOFManager::available() const -{ - return m_DeviceHandle != 0; -} - -bool -GHOST_NDOFManager::event_present() const -{ - if( currentNdofValues.changed >0) { - printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" , - currentNdofValues.time, currentNdofValues.buttons, - currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz, - currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz); - return true; - }else - return false; - -} - -void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const -{ - datas.tx = currentNdofValues.tx; - datas.ty = currentNdofValues.ty; - datas.tz = currentNdofValues.tz; - datas.rx = currentNdofValues.rx; - datas.ry = currentNdofValues.ry; - datas.rz = currentNdofValues.rz; - datas.buttons = currentNdofValues.buttons; - datas.client = currentNdofValues.client; - datas.address = currentNdofValues.address; - datas.time = currentNdofValues.time; - datas.delta = currentNdofValues.delta; -} + return true; + } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 4805707b37b..035f9f22f0a 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -24,28 +24,38 @@ #define _GHOST_NDOFMANAGER_H_ #include "GHOST_System.h" -#include "GHOST_IWindow.h" - class GHOST_NDOFManager { public: - GHOST_NDOFManager(); - virtual ~GHOST_NDOFManager(); - - int deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - - void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const; - - bool available() const; - bool event_present() const; + GHOST_NDOFManager(GHOST_System&); + + virtual ~GHOST_NDOFManager() {}; + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + virtual bool available() = 0; + + // the latest raw data from the device + void updateTranslation(short t[3], GHOST_TUns64 time); + void updateRotation(short r[3], GHOST_TUns64 time); + // this one sends events immediately for changed buttons + void updateButtons(unsigned short b, GHOST_TUns64 time); + + // processes most recent raw data into an NDOFMotion event and sends it + // returns whether an event was sent + bool sendMotionEvent(); protected: - void* m_DeviceHandle; + GHOST_System& m_system; + + short m_translation[3]; + short m_rotation[3]; + unsigned short m_buttons; + + GHOST_TUns64 m_motionTime; + bool m_atRest; }; diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp new file mode 100644 index 00000000000..6eac4194560 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp @@ -0,0 +1,111 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerCocoa.h" +#include <3DconnexionClient/ConnexionClientAPI.h> +#include + +static void SpaceNavAdded(io_connect_t connection) + { + printf("SpaceNav added\n"); + } + +static void SpaceNavRemoved(io_connect_t connection) + { + printf("SpaceNav removed\n"); + } + +static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) + { + GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + GHOST_NDOFManager* manager = system->getNDOFManager(); + switch (messageType) + { + case kConnexionMsgDeviceState: + { + ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + switch (s->command) + { + case kConnexionCmdHandleAxis: + manager->updateTranslation(s->axis, s->time); + manager->updateRotation(s->axis + 3, s->time); + break; + + case kConnexionCmdHandleButtons: + manager->updateButtons(s->buttons, s->time); + break; + } + break; + } + case kConnexionMsgPrefsChanged: + printf("prefs changed\n"); // this includes app switches + break; + case kConnexionMsgDoAction: + printf("do action\n"); // no idea what this means + // 'calibrate device' in System Prefs sends this + break; + default: + printf(" mystery event\n"); + } + } + +GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) + : GHOST_NDOFManager(sys) + { + if (available()) + { + OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); + if (error) + { + printf(" error = %d\n", error); + return; + } + +// char* name = "\pBlender"; +// name[0] = 7; // convert to Pascal string + + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender"/*name*/, + kConnexionClientModeTakeOver, kConnexionMaskAll); + + printf("client id = %d\n", m_clientID); + } + else + { + printf(" SpaceNav driver not found\n"); + // This isn't a hard error, just means the user doesn't have a SpaceNavigator. + } + } + +GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() + { + UnregisterConnexionClient(m_clientID); + CleanupConnexionHandlers(); + } + +bool GHOST_NDOFManagerCocoa::available() + { + extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// [mce] C likes the above line, but Obj-C++ does not. Make sure it works for +// machines without the driver installed! Try it on the QuickSilver. + + return InstallConnexionHandlers != NULL; + } diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h new file mode 100644 index 00000000000..07c4ceb7a60 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -0,0 +1,45 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERCOCOA_H_ +#define _GHOST_NDOFMANAGERCOCOA_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerCocoa(GHOST_System&); + + ~GHOST_NDOFManagerCocoa(); + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available(); + +private: + unsigned short m_clientID; +}; + + +#endif -- cgit v1.2.3 From 195ad03901e4e3e639ce89fec42118e975356064 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 09:30:01 +0000 Subject: more preliminary NDOF handling stuff (untested) --- intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 9 +-- intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 2 + intern/ghost/intern/GHOST_NDOFManagerWin32.h | 46 +++++++++++++++ intern/ghost/intern/GHOST_NDOFManagerX11.h | 46 +++++++++++++++ intern/ghost/intern/GHOST_SystemCocoa.mm | 11 +--- intern/ghost/intern/GHOST_SystemWin32.cpp | 19 +++++-- intern/ghost/intern/GHOST_SystemX11.cpp | 78 +++++++++++++++++--------- intern/ghost/intern/GHOST_SystemX11.h | 3 +- 8 files changed, 166 insertions(+), 48 deletions(-) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerWin32.h create mode 100644 intern/ghost/intern/GHOST_NDOFManagerX11.h (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp index 6eac4194560..0196b2974dd 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp @@ -80,10 +80,8 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) return; } -// char* name = "\pBlender"; -// name[0] = 7; // convert to Pascal string - - m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender"/*name*/, + // Pascal string *and* a four-letter constant. How old-skool. + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender", kConnexionClientModeTakeOver, kConnexionMaskAll); printf("client id = %d\n", m_clientID); @@ -104,8 +102,5 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() bool GHOST_NDOFManagerCocoa::available() { extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); -// [mce] C likes the above line, but Obj-C++ does not. Make sure it works for -// machines without the driver installed! Try it on the QuickSilver. - return InstallConnexionHandlers != NULL; } diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h index 07c4ceb7a60..4f2a2274e35 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -25,6 +25,8 @@ #include "GHOST_NDOFManager.h" +// Event capture is handled within the NDOFManager on Macintosh, +// so there's no need for SystemCocoa to look for them. class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager { diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h new file mode 100644 index 00000000000..a09808dbe38 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -0,0 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERWIN32_H_ +#define _GHOST_NDOFMANAGERWIN32_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerWin32(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available() + { + // always available since RawInput is built into Windows + return true; + } +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h new file mode 100644 index 00000000000..8f9c819a481 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -0,0 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERX11_H_ +#define _GHOST_NDOFMANAGERX11_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerX11 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerX11(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available() + { + // never available since I've not yet written it! + return false; + } +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 91da1fb2d4b..1ab0794548e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -54,7 +54,7 @@ #include "GHOST_TimerTask.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowCocoa.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerCocoa.h" #include "AssertMacros.h" #pragma mark KeyMap, mouse converters @@ -601,13 +601,8 @@ GHOST_TSuccess GHOST_SystemCocoa::init() { GHOST_TSuccess success = GHOST_System::init(); if (success) { - //ProcessSerialNumber psn; - - //Carbon stuff to move window & menu to foreground - /*if (!GetCurrentProcess(&psn)) { - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); - }*/ + + m_ndofManager = new GHOST_NDOFManagerCocoa(*this); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 829f0997377..14b6b16e6fb 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -73,7 +73,7 @@ #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerWin32.h" // Key code values not found in winuser.h #ifndef VK_MINUS @@ -347,6 +347,8 @@ GHOST_TSuccess GHOST_SystemWin32::init() { GHOST_TSuccess success = GHOST_System::init(); + m_ndofManager = new GHOST_NDOFManagerWin32(*this); + /* Disable scaling on high DPI displays on Vista */ HMODULE user32 = ::LoadLibraryA("user32.dll"); typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); @@ -736,9 +738,6 @@ vendor ID No other registered devices use the c62_ space, so a simple mask will work! */ - short t[3], r[3]; // defined here just for quick testing, - unsigned short buttons; // will maintain shared copy for all NDOF events - // multiple events per RAWHID? MSDN hints at this. printf("%d events\n", raw.data.hid.dwCount); @@ -754,14 +753,24 @@ No other registered devices use the c62_ space, so a simple mask will work! switch (packetType) { case 1: // translation + { + short t[3]; memcpy(t, data + 1, sizeof(t)); printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + m_ndofManager->updateTranslation(t, getMilliseconds()); break; + } case 2: // rotation + { + short r[3]; memcpy(r, data + 1, sizeof(r)); printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + m_ndofManager->updateRotation(r, getMilliseconds()); break; + } case 3: // buttons + { + unsigned short buttons; memcpy(&buttons, data + 1, sizeof(buttons)); printf("buttons:"); if (buttons) @@ -774,7 +783,9 @@ No other registered devices use the c62_ space, so a simple mask will work! } else printf(" none\n"); + m_ndofManager->updateButtons(buttons, getMilliseconds()); break; + } } } diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 1ae9b666c6b..a70162a5039 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -38,14 +38,14 @@ #include "GHOST_EventButton.h" #include "GHOST_EventWheel.h" #include "GHOST_EventNDOF.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerX11.h" #include "GHOST_DisplayManagerX11.h" #include "GHOST_Debug.h" #include #include -#include /* allow detectable autorepeate */ +#include /* allow detectable autorepeat */ #ifdef __sgi @@ -67,10 +67,11 @@ #include // for fprintf only #include // for exit +// [mce] these are for communication with the plugin typedef struct NDOFPlatformInfo { Display *display; Window window; - volatile GHOST_TEventNDOFData *currValues; +// volatile GHOST_TEventNDOFData *currValues; Atom cmdAtom; Atom motionAtom; Atom btnPressAtom; @@ -79,7 +80,6 @@ typedef struct NDOFPlatformInfo { static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0}; - //these are for copy and select copy static char *txt_cut_buffer= NULL; static char *txt_select_buffer= NULL; @@ -142,7 +142,7 @@ GHOST_SystemX11( m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000); - /* use detectable autorepeate, mac and windows also do this */ + /* use detectable autorepeat, mac and windows also do this */ int use_xkb; int xkb_opcode, xkb_event, xkb_error; int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion; @@ -168,6 +168,9 @@ init( GHOST_TSuccess success = GHOST_System::init(); if (success) { + + m_ndofManager = new GHOST_NDOFManagerX11; + m_displayManager = new GHOST_DisplayManagerX11(this); if (m_displayManager) { @@ -246,9 +249,6 @@ createWindow( GHOST_WindowX11 * window = 0; if (!m_display) return 0; - - - window = new GHOST_WindowX11 ( this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual @@ -628,29 +628,49 @@ GHOST_SystemX11::processEvent(XEvent *xe) } else #endif if (sNdofInfo.currValues) { - static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; +// static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; if (xcme.message_type == sNdofInfo.motionAtom) { - data.changed = 1; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.tx = xcme.data.s[2] >> 2; - data.ty = xcme.data.s[3] >> 2; - data.tz = xcme.data.s[4] >> 2; - data.rx = xcme.data.s[5]; - data.ry = xcme.data.s[6]; - data.rz =-xcme.data.s[7]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, data); +// data.changed = 1; +// data.delta = xcme.data.s[8] - data.time; +// data.time = xcme.data.s[8]; +// data.tx = xcme.data.s[2] >> 2; +// data.ty = xcme.data.s[3] >> 2; +// data.tz = xcme.data.s[4] >> 2; +// data.rx = xcme.data.s[5]; +// data.ry = xcme.data.s[6]; +// data.rz =-xcme.data.s[7]; + + short t[3], r[3]; + t[0] = xcme.data.s[2] >> 2; + t[1] = xcme.data.s[3] >> 2; + t[2] = xcme.data.s[4] >> 2; + r[0] = xcme.data.s[5]; + r[1] = xcme.data.s[6]; + r[2] =-xcme.data.s[7]; + + // [mce] look into this soon, as in find out why some values + // are shifted and where this message originates. + + m_ndofManager->updateTranslation(t, getMilliseconds); + m_ndofManager->updateRotation(r, getMilliseconds); + +// g_event = new GHOST_EventNDOF(getMilliSeconds(), +// GHOST_kEventNDOFMotion, +// window, data); + } else if (xcme.message_type == sNdofInfo.btnPressAtom) { - data.changed = 2; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.buttons = xcme.data.s[2]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFButton, - window, data); +// data.changed = 2; +// data.delta = xcme.data.s[8] - data.time; +// data.time = xcme.data.s[8]; +// data.buttons = xcme.data.s[2]; + + unsigned short buttons = xcme.data.s[2]; + m_ndofManager->updateButtons(buttons, getMilliseconds()); + +// g_event = new GHOST_EventNDOF(getMilliSeconds(), +// GHOST_kEventNDOFButton, +// window, data); } } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { XWindowAttributes attr; @@ -814,6 +834,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) } } +/* void * GHOST_SystemX11:: prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) @@ -825,6 +846,7 @@ prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) sNdofInfo.currValues = currentNdofValues; return (void*)&sNdofInfo; } +*/ GHOST_TSuccess GHOST_SystemX11:: diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index ee6cbedb2ae..d00f83aa8ea 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -202,10 +202,12 @@ public: return m_display; } +/* [mce] is this needed? void * prepareNdofInfo( volatile GHOST_TEventNDOFData *current_values ); +*/ /* Helped function for get data from the clipboard. */ void getClipboard_xcout(XEvent evt, Atom sel, Atom target, @@ -317,4 +319,3 @@ private : }; #endif - -- cgit v1.2.3 From 47ea957c9d91ec03aeceaf241d9cd5b898ba811c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 23 Jul 2010 06:36:08 +0000 Subject: provided a way for NDOF manager to poke SystemCocoa about out-of-loop events --- intern/ghost/intern/GHOST_SystemCocoa.h | 12 ++++++++---- intern/ghost/intern/GHOST_SystemCocoa.mm | 7 +++++++ 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 0949dca5acc..08cb5037981 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -234,14 +234,18 @@ public: * @return Indication whether the event was handled. */ GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); - + /** * Handles the Cocoa event telling the application has become active (again) * @return Indication whether the event was handled. */ GHOST_TSuccess handleApplicationBecomeActiveEvent(); - - + + /** + * External objects should call this when they send an event outside processEvents. + */ + void notifyExternalEventProcessed(); + protected: /** * Initializes the system. @@ -298,7 +302,7 @@ protected: /** Start time at initialization. */ GHOST_TUns64 m_start_time; - /** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */ + /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; /** Raised window is not yet known by the window manager, so delay application become active event handling */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 1ab0794548e..05bc93f937d 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -994,6 +994,8 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); +// m_outsideLoopEventProcessed |= m_ndofManager->sendMotionEvent(); + if (m_outsideLoopEventProcessed) { m_outsideLoopEventProcessed = false; return true; @@ -1038,6 +1040,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() return GHOST_kSuccess; } +void GHOST_SystemCocoa::notifyExternalEventProcessed() +{ + m_outsideLoopEventProcessed = true; +} + //Note: called from NSWindow delegate GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window) { -- cgit v1.2.3 From 6216199af8d5046d25a2b74983cc2f86904f0553 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 23 Jul 2010 06:45:59 +0000 Subject: SpaceNav event capture for MacOS, dispatch for all platforms. To compile this, you need their Mac driver installed and to send '-weak_framework 3DconnexionClient' to the linker. I'm also exploring a HID Manager version, bypassing their driver (and any licensing issues). --- intern/ghost/intern/GHOST_NDOFManager.cpp | 3 +++ intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 15 +++++++++++---- intern/ghost/intern/GHOST_System.cpp | 3 +++ 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 787811fc69b..120805733b4 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -79,6 +79,9 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; + printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); + fflush(stdout); + m_system.pushEvent(event); // 'at rest' test goes at the end so that the first 'rest' event gets sent diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp index 0196b2974dd..c4a8a2f1831 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp @@ -21,8 +21,12 @@ */ #include "GHOST_NDOFManagerCocoa.h" -#include <3DconnexionClient/ConnexionClientAPI.h> -#include +#include "GHOST_SystemCocoa.h" + +extern "C" { + #include <3DconnexionClient/ConnexionClientAPI.h> + #include + } static void SpaceNavAdded(io_connect_t connection) { @@ -36,7 +40,7 @@ static void SpaceNavRemoved(io_connect_t connection) static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) { - GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); GHOST_NDOFManager* manager = system->getNDOFManager(); switch (messageType) { @@ -48,10 +52,12 @@ static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void * case kConnexionCmdHandleAxis: manager->updateTranslation(s->axis, s->time); manager->updateRotation(s->axis + 3, s->time); + system->notifyExternalEventProcessed(); break; case kConnexionCmdHandleButtons: manager->updateButtons(s->buttons, s->time); + system->notifyExternalEventProcessed(); break; } break; @@ -101,6 +107,7 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() bool GHOST_NDOFManagerCocoa::available() { - extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// ^-- not needed since the entire framework is weak-linked return InstallConnexionHandlers != NULL; } diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 70ff5a02924..4e0888a87a7 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -196,6 +196,9 @@ bool GHOST_System::getFullScreen(void) bool GHOST_System::dispatchEvents() { + // NDOF Motion event is sent only once per dispatch, so do it now: + m_ndofManager->sendMotionEvent(); + bool handled; if (m_eventManager) { if (m_input_fidelity_hint == LO_FI) -- cgit v1.2.3 From c4c46e4403826a850b4f2fe735ee38560235c95c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 23 Jul 2010 10:03:22 +0000 Subject: mostly formatting: put SystemCocoa on a diet of a thousand tabs, also spotted and fixed a leaky switch-case (trackpad gesture for 'rotate') --- intern/ghost/intern/GHOST_SystemCocoa.mm | 581 +++++++++++++++---------------- 1 file changed, 282 insertions(+), 299 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 05bc93f937d..3ab69ac3f64 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -235,8 +235,8 @@ static GHOST_TButtonMask convertButton(int button) * @return Ghost key code */ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) -{ - +{ + //printf("\nrecvchar %c 0x%x",recvChar,recvChar); switch (rawCode) { /*Physical keycodes not used due to map changes in int'l keyboards @@ -266,7 +266,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_ANSI_X: return GHOST_kKeyX; case kVK_ANSI_Y: return GHOST_kKeyY; case kVK_ANSI_Z: return GHOST_kKeyZ;*/ - + /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/ case kVK_ISO_Section: return GHOST_kKeyUnknown; case kVK_ANSI_1: return GHOST_kKey1; @@ -279,7 +279,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_ANSI_8: return GHOST_kKey8; case kVK_ANSI_9: return GHOST_kKey9; case kVK_ANSI_0: return GHOST_kKey0; - + case kVK_ANSI_Keypad0: return GHOST_kKeyNumpad0; case kVK_ANSI_Keypad1: return GHOST_kKeyNumpad1; case kVK_ANSI_Keypad2: return GHOST_kKeyNumpad2; @@ -318,24 +318,24 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_F18: return GHOST_kKeyF18; case kVK_F19: return GHOST_kKeyF19; case kVK_F20: return GHOST_kKeyF20; - + case kVK_UpArrow: return GHOST_kKeyUpArrow; case kVK_DownArrow: return GHOST_kKeyDownArrow; case kVK_LeftArrow: return GHOST_kKeyLeftArrow; case kVK_RightArrow: return GHOST_kKeyRightArrow; - + case kVK_Return: return GHOST_kKeyEnter; case kVK_Delete: return GHOST_kKeyBackSpace; case kVK_ForwardDelete: return GHOST_kKeyDelete; case kVK_Escape: return GHOST_kKeyEsc; case kVK_Tab: return GHOST_kKeyTab; case kVK_Space: return GHOST_kKeySpace; - + case kVK_Home: return GHOST_kKeyHome; case kVK_End: return GHOST_kKeyEnd; case kVK_PageUp: return GHOST_kKeyUpPage; case kVK_PageDown: return GHOST_kKeyDownPage; - + /*case kVK_ANSI_Minus: return GHOST_kKeyMinus; case kVK_ANSI_Equal: return GHOST_kKeyEqual; case kVK_ANSI_Comma: return GHOST_kKeyComma; @@ -347,12 +347,12 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_ANSI_LeftBracket: return GHOST_kKeyLeftBracket; case kVK_ANSI_RightBracket: return GHOST_kKeyRightBracket; case kVK_ANSI_Grave: return GHOST_kKeyAccentGrave;*/ - + case kVK_VolumeUp: case kVK_VolumeDown: case kVK_Mute: return GHOST_kKeyUnknown; - + default: /* alphanumerical or punctuation key that is remappable in int'l keyboards */ if ((recvChar >= 'A') && (recvChar <= 'Z')) { @@ -363,42 +363,38 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 KeyboardLayoutRef keyLayout; UCKeyboardLayout *uchrData; - + KLGetCurrentKeyboardLayout(&keyLayout); KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **) &uchrData); /*get actual character value of the "remappable" keys in int'l keyboards, if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger), then fallback on using the received charactersIgnoringModifiers */ - if (uchrData) - { + if (uchrData) { UInt32 deadKeyState=0; UniCharCount actualStrLength=0; - + UCKeyTranslate(uchrData, rawCode, keyAction, 0, - LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar); - - } + LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar); + } #else /* Leopard and Snow Leopard 64bit compatible API*/ CFDataRef uchrHandle; /*the keyboard layout*/ TISInputSourceRef kbdTISHandle; - + kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource(); uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData); CFRelease(kbdTISHandle); - + /*get actual character value of the "remappable" keys in int'l keyboards, if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger), then fallback on using the received charactersIgnoringModifiers */ - if (uchrHandle) - { + if (uchrHandle) { UInt32 deadKeyState=0; UniCharCount actualStrLength=0; - + UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar); - } #endif switch (recvChar) { @@ -476,9 +472,9 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) { int result; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + result = fromcocoa_request_qtcodec_settings(C, op); - + [pool drain]; return result; } @@ -549,7 +545,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() struct timeval boottime; size_t len; char *rstring = NULL; - + m_modifierMask =0; m_pressedMouseButtons =0; m_isGestureInProgress = false; @@ -568,27 +564,27 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; len = sizeof(struct timeval); - + sysctl(mib, 2, &boottime, &len, NULL, 0); m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000)); - + //Detect multitouch trackpad mib[0] = CTL_HW; mib[1] = HW_MODEL; sysctl( mib, 2, NULL, &len, NULL, 0 ); rstring = (char*)malloc( len ); sysctl( mib, 2, rstring, &len, NULL, 0 ); - + //Hack on MacBook revision, as multitouch avail. function missing m_hasMultiTouchTrackpad = (strstr(rstring,"MacBookAir") || (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))); - + free( rstring ); rstring = NULL; - + m_ignoreWindowSizedMessages = false; - + m_input_fidelity_hint = HI_FI; // just for testing... } @@ -599,63 +595,63 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa() GHOST_TSuccess GHOST_SystemCocoa::init() { - GHOST_TSuccess success = GHOST_System::init(); - if (success) { + GHOST_TSuccess success = GHOST_System::init(); + if (success) { m_ndofManager = new GHOST_NDOFManagerCocoa(*this); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { [NSApplication sharedApplication]; - + if ([NSApp mainMenu] == nil) { NSMenu *mainMenubar = [[NSMenu alloc] init]; NSMenuItem *menuItem; NSMenu *windowMenu; NSMenu *appMenu; - + //Create the application menu appMenu = [[NSMenu alloc] initWithTitle:@"Blender"]; - + [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appMenu addItem:[NSMenuItem separatorItem]]; - + menuItem = [appMenu addItemWithTitle:@"Hide Blender" action:@selector(hide:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + menuItem = [appMenu addItemWithTitle:@"Hide others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)]; - + [appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - + menuItem = [appMenu addItemWithTitle:@"Quit Blender" action:@selector(terminate:) keyEquivalent:@"q"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + menuItem = [[NSMenuItem alloc] init]; [menuItem setSubmenu:appMenu]; - + [mainMenubar addItem:menuItem]; [menuItem release]; [NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; //Needed for 10.5 [appMenu release]; - + //Create the window menu windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - + menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""]; - + menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + menuItem = [[NSMenuItem alloc] init]; [menuItem setSubmenu:windowMenu]; - + [mainMenubar addItem:menuItem]; [menuItem release]; - + [NSApp setMainMenu:mainMenubar]; [NSApp setWindowsMenu:windowMenu]; [windowMenu release]; @@ -666,12 +662,12 @@ GHOST_TSuccess GHOST_SystemCocoa::init() [appDelegate setSystemCocoa:this]; [NSApp setDelegate:appDelegate]; } - + [NSApp finishLaunching]; - + [pool drain]; - } - return success; + } + return success; } @@ -681,11 +677,10 @@ GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const { //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime]) struct timeval currentTime; - + gettimeofday(¤tTime, NULL); - + //Return timestamp of system uptime - return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time); } @@ -708,11 +703,11 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; - + //Returns max window contents (excluding title bar...) NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; - + width = contentRect.size.width; height = contentRect.size.height; @@ -721,7 +716,7 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns GHOST_IWindow* GHOST_SystemCocoa::createWindow( - const STR_String& title, + const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -733,59 +728,58 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( const GHOST_TEmbedderWindowID parentWindow ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_IWindow* window = 0; - + //Get the available rect for including window contents NSRect frame = [[NSScreen mainScreen] visibleFrame]; NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; - + //Ensures window top left is inside this available rect left = left > contentRect.origin.x ? left : contentRect.origin.x; top = top > contentRect.origin.y ? top : contentRect.origin.y; - + window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); - if (window) { - if (window->getValid()) { - // Store the pointer to the window - GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); - m_windowManager->addWindow(window); - m_windowManager->setActiveWindow(window); + if (window) { + if (window->getValid()) { + // Store the pointer to the window + GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation) - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window)); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window)); pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); - - } - else { - GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n"); - delete window; - window = 0; - } - } + } + else { + GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n"); + delete window; + window = 0; + } + } else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n"); } [pool drain]; - return window; + return window; } GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual) -{ +{ GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow(); *window = currentWindow; - + if(!currentWindow) return GHOST_kFailure; - + return currentWindow->setState(GHOST_kWindowStateFullScreen); } GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void) -{ +{ GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow(); if(!currentWindow) return GHOST_kFailure; - + return currentWindow->setState(GHOST_kWindowStateNormal); } @@ -796,12 +790,13 @@ GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void) */ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const { - NSPoint mouseLoc = [NSEvent mouseLocation]; - - // Returns the mouse location in screen coordinates - x = (GHOST_TInt32)mouseLoc.x; - y = (GHOST_TInt32)mouseLoc.y; - return GHOST_kSuccess; + NSPoint mouseLoc = [NSEvent mouseLocation]; + + // Returns the mouse location in screen coordinates + x = (GHOST_TInt32)mouseLoc.x; + y = (GHOST_TInt32)mouseLoc.y; + + return GHOST_kSuccess; } /** @@ -814,12 +809,12 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 if (!window) return GHOST_kFailure; setMouseCursorPosition(x, y); - + //Force mouse move event (not pushed by Cocoa) window->screenToClient(x, y, wx, wy); pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, wx,wy)); m_outsideLoopEventProcessed = true; - + return GHOST_kSuccess; } @@ -832,18 +827,18 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSScreen *windowScreen = window->getScreen(); NSRect screenRect = [windowScreen frame]; - + //Set position relative to current screen xf -= screenRect.origin.x; yf -= screenRect.origin.y; - + //Quartz Display Services uses the old coordinates (top left origin) yf = screenRect.size.height -yf; - + CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf)); [pool drain]; - return GHOST_kSuccess; + return GHOST_kSuccess; } @@ -853,19 +848,19 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false); keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false); keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false); - - return GHOST_kSuccess; + + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const { buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); + buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight); buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle); buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4); buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5); - return GHOST_kSuccess; + return GHOST_kSuccess; } @@ -975,10 +970,10 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) case NSEventTypeGesture: case NSEventTypeSwipe: break; */ - + default: break; - /* Unused events: + /* Unused events: NSMouseEntered = 8, NSMouseExited = 9, NSAppKitDefined = 13, @@ -988,20 +983,18 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) NSCursorUpdate = 17,*/ } } while (event != nil); - + [pool drain]; - + if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); - -// m_outsideLoopEventProcessed |= m_ndofManager->sendMotionEvent(); - + if (m_outsideLoopEventProcessed) { m_outsideLoopEventProcessed = false; return true; } - - return anyProcessed; + + return anyProcessed; } @@ -1012,7 +1005,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() //(that is when update events are sent to another application) unsigned int modifiers; GHOST_IWindow* window = m_windowManager->getActiveWindow(); - + if (!window) { m_needDelayedApplicationBecomeActiveEventProcessing = true; return GHOST_kFailure; @@ -1020,7 +1013,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() else m_needDelayedApplicationBecomeActiveEventProcessing = false; modifiers = [[[NSApplication sharedApplication] currentEvent] modifierFlags]; - + if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); } @@ -1033,9 +1026,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); } - + m_modifierMask = modifiers; - + m_outsideLoopEventProcessed = true; return GHOST_kSuccess; } @@ -1051,37 +1044,36 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, if (!validWindow(window)) { return GHOST_kFailure; } - switch(eventType) - { - case GHOST_kEventWindowClose: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); - break; - case GHOST_kEventWindowActivate: - m_windowManager->setActiveWindow(window); - window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); - break; - case GHOST_kEventWindowDeactivate: - m_windowManager->setWindowInactive(window); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); - break; - case GHOST_kEventWindowUpdate: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); - break; - case GHOST_kEventWindowMove: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) ); - break; - case GHOST_kEventWindowSize: - if (!m_ignoreWindowSizedMessages) - { - window->updateDrawingContext(); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); - } - break; - default: - return GHOST_kFailure; - break; - } + + switch(eventType) { + case GHOST_kEventWindowClose: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); + break; + case GHOST_kEventWindowActivate: + m_windowManager->setActiveWindow(window); + window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); + break; + case GHOST_kEventWindowDeactivate: + m_windowManager->setWindowInactive(window); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); + break; + case GHOST_kEventWindowUpdate: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); + break; + case GHOST_kEventWindowMove: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) ); + break; + case GHOST_kEventWindowSize: + if (!m_ignoreWindowSizedMessages) { + window->updateDrawingContext(); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + } + break; + default: + return GHOST_kFailure; + break; + } m_outsideLoopEventProcessed = true; return GHOST_kSuccess; @@ -1094,76 +1086,76 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType if (!validWindow(window)) { return GHOST_kFailure; } - switch(eventType) - { + + switch(eventType) { case GHOST_kEventDraggingEntered: case GHOST_kEventDraggingUpdated: case GHOST_kEventDraggingExited: pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,NULL)); break; - + case GHOST_kEventDraggingDropDone: { GHOST_TUns8 * temp_buff; GHOST_TStringArray *strArray; NSArray *droppedArray; - size_t pastedTextSize; + size_t pastedTextSize; NSString *droppedStr; GHOST_TEventDataPtr eventData; int i; if (!data) return GHOST_kFailure; - + switch (draggedObjectType) { case GHOST_kDragnDropTypeFilenames: droppedArray = (NSArray*)data; - + strArray = (GHOST_TStringArray*)malloc(sizeof(GHOST_TStringArray)); if (!strArray) return GHOST_kFailure; - + strArray->count = [droppedArray count]; if (strArray->count == 0) return GHOST_kFailure; - + strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*)); - + for (i=0;icount;i++) { droppedStr = [droppedArray objectAtIndex:i]; - + pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); - + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); + if (!temp_buff) { strArray->count = i; break; } - + strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize); temp_buff[pastedTextSize] = '\0'; - + strArray->strings[i] = temp_buff; } - eventData = (GHOST_TEventDataPtr) strArray; + eventData = (GHOST_TEventDataPtr) strArray; break; - + case GHOST_kDragnDropTypeString: droppedStr = (NSString*)data; pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); - + if (temp_buff == NULL) { return GHOST_kFailure; } - + strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize); - + temp_buff[pastedTextSize] = '\0'; - + eventData = (GHOST_TEventDataPtr) temp_buff; break; - + case GHOST_kDragnDropTypeBitmap: { NSImage *droppedImg = (NSImage*)data; @@ -1176,13 +1168,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA,*bitmapImage=nil; NSEnumerator *enumerator; NSImageRep *representation; - + ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect, 0); if (!ibuf) { [droppedImg release]; return GHOST_kFailure; } - + /*Get the bitmap of the image*/ enumerator = [[droppedImg representations] objectEnumerator]; while ((representation = [enumerator nextObject])) { @@ -1192,7 +1184,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType } } if (bitmapImage == nil) return GHOST_kFailure; - + if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0) && ![bitmapImage isPlanar]) { /* Try a fast copy if the image is a meshed RGBA 32bit bitmap*/ @@ -1207,11 +1199,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType else { /* Tell cocoa image resolution is same as current system one */ [bitmapImage setSize:imgSize]; - + /* Convert the image in a RGBA 32bit format */ - /* As Core Graphics does not support contextes with non premutliplied alpha, + /* As Core Graphics does not support contexts with non premutliplied alpha, we need to get alpha key values in a separate batch */ - + /* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */ blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:imgSize.width @@ -1221,12 +1213,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType bitmapFormat:(NSBitmapFormat)0 bytesPerRow:4*imgSize.width bitsPerPixel:32/*RGB format padded to 32bits*/]; - + [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGB]]; [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - + rasterRGB = (GHOST_TUns8*)[blBitmapFormatImageRGB bitmapData]; if (rasterRGB == NULL) { [bitmapImage release]; @@ -1234,7 +1226,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType [droppedImg release]; return GHOST_kFailure; } - + /* Then get Alpha values by getting the RGBA image (that is premultiplied btw) */ blBitmapFormatImageRGBA = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:imgSize.width @@ -1244,12 +1236,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType bitmapFormat:(NSBitmapFormat)0 bytesPerRow:4*imgSize.width bitsPerPixel:32/* RGBA */]; - + [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGBA]]; [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - + rasterRGBA = (GHOST_TUns8*)[blBitmapFormatImageRGBA bitmapData]; if (rasterRGBA == NULL) { [bitmapImage release]; @@ -1258,37 +1250,37 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType [droppedImg release]; return GHOST_kFailure; } - + /*Copy the image to ibuf, flipping it vertically*/ toIBuf = (GHOST_TUns8*)ibuf->rect; for (y = 0; y < imgSize.height; y++) { for (x = 0; x < imgSize.width; x++) { to_i = (imgSize.height-y-1)*imgSize.width + x; from_i = y*imgSize.width + x; - + toIBuf[4*to_i] = rasterRGB[4*from_i]; /* R */ toIBuf[4*to_i+1] = rasterRGB[4*from_i+1]; /* G */ toIBuf[4*to_i+2] = rasterRGB[4*from_i+2]; /* B */ toIBuf[4*to_i+3] = rasterRGBA[4*from_i+3]; /* A */ } } - + [blBitmapFormatImageRGB release]; [blBitmapFormatImageRGBA release]; [droppedImg release]; } - + eventData = (GHOST_TEventDataPtr) ibuf; - } break; - + } + default: return GHOST_kFailure; break; } pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData)); - } break; + } default: return GHOST_kFailure; } @@ -1300,11 +1292,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() { GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow(); - + //Discard quit event if we are in cursor grab sequence if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal)) return GHOST_kExitCancel; - + //Check open windows if some changes are not saved if (m_windowManager->getAnyModifiedState()) { @@ -1328,7 +1320,7 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() m_outsideLoopEventProcessed = true; return GHOST_kExitNow; } - + return GHOST_kExitCancel; } @@ -1340,11 +1332,11 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) char * temp_buff; size_t filenameTextSize; GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow(); - + if (!window) { return NO; } - + //Discard event if we are in cursor grab sequence, it'll lead to "stuck cursor" situation if the alert panel is raised if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal)) return GHOST_kExitCancel; @@ -1366,15 +1358,15 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) if (confirmOpen == NSAlertAlternateReturn) { filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; - + temp_buff = (char*) malloc(filenameTextSize+1); - + if (temp_buff == NULL) { return GHOST_kFailure; } - + strncpy(temp_buff, [filepath cStringUsingEncoding:NSISOLatin1StringEncoding], filenameTextSize); - + temp_buff[filenameTextSize] = '\0'; pushEvent(new GHOST_EventString(getMilliSeconds(),GHOST_kEventOpenMainFile,window,(GHOST_TEventDataPtr) temp_buff)); @@ -1395,7 +1387,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + GHOST_TabletData& ct = window->GetCocoaTabletData(); GHOST_TTabletMode active_tool; @@ -1461,7 +1453,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) } GHOST_TabletData& ct = window->GetCocoaTabletData(); - + ct.Pressure = [event pressure]; NSPoint tilt = [event tilt]; ct.Xtilt = tilt.x; @@ -1512,8 +1504,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) static float warp_dx = 0, warp_dy = 0; // need to reset these. e.g. each grab operation should get its own. // ^^ not currently useful, try m_cursorDelta_* instead. - switch ([event type]) - { + switch ([event type]) { case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: @@ -1525,7 +1516,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); break; - + case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: @@ -1539,7 +1530,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) // cheap hack, should reset when grab ends. warp_dx = warp_dy = 0; break; - + case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: @@ -1556,128 +1547,121 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) event_dy = -event_dy; //Strange Apple implementation (inverted coordinates for the deltaY) ... - switch (window->getCursorGrabMode()) { case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move - { + { printf(" - grab hide\n"); GHOST_TInt32 x_warp, y_warp, x_accum, y_accum; - + window->getCursorGrabInitPos(x_warp, y_warp); - + window->getCursorGrabAccum(x_accum, y_accum); x_accum += event_dx; y_accum += event_dy; window->setCursorGrabAccum(x_accum, y_accum); - + pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum)); - } break; + } case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries - { + { NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; GHOST_TInt32 x_accum, y_accum, x_cur, y_cur; GHOST_Rect bounds, windowBounds, correctedBounds; - + /* fallback to window bounds */ if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); - + //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates window->getClientBounds(windowBounds); window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b; correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t; - + //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); x_accum += event_dx - m_cursorDelta_x; y_accum += event_dy - m_cursorDelta_y; window->setCursorGrabAccum(x_accum, y_accum); - - + //Warp mouse cursor if needed x_mouse += event_dx - m_cursorDelta_x; y_mouse += event_dy - m_cursorDelta_y; correctedBounds.wrapPoint(x_mouse, y_mouse, 2); - + //Compensate for mouse moved event taking cursor position set into account m_cursorDelta_x = x_mouse-mousePos.x; m_cursorDelta_y = y_mouse-mousePos.y; - + //Set new cursor position window->clientToScreen(x_mouse, y_mouse, x_cur, y_cur); setMouseCursorPosition(x_cur, y_cur); /* wrap */ - + //Post event window->getCursorGrabInitPos(x_cur, y_cur); pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_cur + x_accum, y_cur + y_accum)); - } + break; + } default: - { //Normal cursor operation: send mouse position in window pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y)); m_cursorDelta_x=0; m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter - warp_dx = 0; warp_dy = 0; - } - break; - } - break; - } + } // END cursor grab mode + break; + } // END mouse moved case NSScrollWheel: - { - /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ - if (m_hasMultiTouchTrackpad and m_isGestureInProgress) { - NSPoint mousePos = [event locationInWindow]; - double dx = [event deltaX]; - double dy = -[event deltaY]; - - const double deltaMax = 50.0; - - if ((dx == 0) && (dy == 0)) break; - - /* Quadratic acceleration */ - dx = dx*(fabs(dx)+0.5); - if (dx<0.0) dx-=0.5; else dx+=0.5; - if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; - - dy = dy*(fabs(dy)+0.5); - if (dy<0.0) dy-=0.5; else dy+=0.5; - if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; - - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy)); - } - else { - GHOST_TInt32 delta; - - double deltaF = [event deltaY]; - if (deltaF == 0.0) break; //discard trackpad delta=0 events - - delta = deltaF > 0.0 ? 1 : -1; - pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); - } + /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ + if (m_hasMultiTouchTrackpad and m_isGestureInProgress) { + NSPoint mousePos = [event locationInWindow]; + double dx = [event deltaX]; + double dy = -[event deltaY]; + + const double deltaMax = 50.0; + + if ((dx == 0) && (dy == 0)) break; + + /* Quadratic acceleration */ + dx = dx*(fabs(dx)+0.5); + if (dx<0.0) dx-=0.5; else dx+=0.5; + if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; + + dy = dy*(fabs(dy)+0.5); + if (dy<0.0) dy-=0.5; else dy+=0.5; + if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; + + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy)); + } + else { + GHOST_TInt32 delta; + + double deltaF = [event deltaY]; + if (deltaF == 0.0) break; //discard trackpad delta=0 events + + delta = deltaF > 0.0 ? 1 : -1; + pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); } break; - + case NSEventTypeMagnify: { - NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0)); - } + NSPoint mousePos = [event locationInWindow]; + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0)); break; - + } case NSEventTypeRotate: { - NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0)); + NSPoint mousePos = [event locationInWindow]; + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0)); + break; } case NSEventTypeBeginGesture: m_isGestureInProgress = true; @@ -1688,8 +1672,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) default: printf(" unknown event type %d\n", [event type]); return GHOST_kFailure; - } - + } + return GHOST_kSuccess; } @@ -1710,7 +1694,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + switch ([event type]) { case NSKeyDown: case NSKeyUp: @@ -1723,7 +1707,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) keyCode = convertKey([event keyCode],0, [event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp); - + characters = [event characters]; if ([characters length]>0) { //Check for dead keys //Convert characters to iso latin 1 encoding @@ -1735,7 +1719,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) } else ascii= 0; - + if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask)) break; //Cmd-Q is directly handled by Cocoa @@ -1747,10 +1731,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) //printf("\nKey up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii); } break; - + case NSFlagsChanged: modifiers = [event modifierFlags]; - + if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); } @@ -1763,65 +1747,64 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); } - + m_modifierMask = modifiers; break; - + default: return GHOST_kFailure; break; } - + return GHOST_kSuccess; } - #pragma mark Clipboard get/set GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const { GHOST_TUns8 * temp_buff; size_t pastedTextSize; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - + if (pasteBoard == nil) { [pool drain]; return NULL; } - + NSArray *supportedTypes = [NSArray arrayWithObjects: NSStringPboardType, nil]; - + NSString *bestType = [[NSPasteboard generalPasteboard] availableTypeFromArray:supportedTypes]; - + if (bestType == nil) { [pool drain]; return NULL; } - + NSString * textPasted = [pasteBoard stringForType:NSStringPboardType]; if (textPasted == nil) { [pool drain]; return NULL; } - + pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; - + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); if (temp_buff == NULL) { [pool drain]; return NULL; } - + strncpy((char*)temp_buff, [textPasted cStringUsingEncoding:NSISOLatin1StringEncoding], pastedTextSize); - + temp_buff[pastedTextSize] = '\0'; [pool drain]; @@ -1836,26 +1819,26 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const { NSString *textToCopy; - + if(selection) {return;} // for copying the selection, used on X11 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - + if (pasteBoard == nil) { [pool drain]; return; } - + NSArray *supportedTypes = [NSArray arrayWithObject:NSStringPboardType]; - + [pasteBoard declareTypes:supportedTypes owner:nil]; - + textToCopy = [NSString stringWithCString:buffer encoding:NSISOLatin1StringEncoding]; - + [pasteBoard setString:textToCopy forType:NSStringPboardType]; - + [pool drain]; } @@ -1868,23 +1851,23 @@ const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const NSFileManager *fileManager; NSString *basePath; NSArray *paths; - + paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSLocalDomainMask, YES); - + if ([paths count] > 0) basePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Blender"]; else { //Fall back to standard unix path in case of issue basePath = @"/usr/share/blender"; } - + /* Ensure path exists, creates it if needed */ fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:basePath isDirectory:NULL]) { [fileManager createDirectoryAtPath:basePath attributes:nil]; } - + strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - + [pool drain]; return tempPath; } @@ -1904,15 +1887,15 @@ const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const else { //Fall back to HOME in case of issue basePath = [NSHomeDirectory() stringByAppendingPathComponent:@".blender"]; } - + /* Ensure path exists, creates it if needed */ fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:basePath isDirectory:NULL]) { [fileManager createDirectoryAtPath:basePath attributes:nil]; } - + strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - + [pool drain]; return tempPath; } -- cgit v1.2.3 From a51ebf247fe97bd40e04d1d24dbb89e200e9fc09 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 24 Jul 2010 06:49:24 +0000 Subject: Renamed Mac file to exclude it from Windows build. Revoke this cowardly commit once I figure out how to properly fix the build script! --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 113 ++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.mm (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm new file mode 100644 index 00000000000..c4a8a2f1831 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -0,0 +1,113 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerCocoa.h" +#include "GHOST_SystemCocoa.h" + +extern "C" { + #include <3DconnexionClient/ConnexionClientAPI.h> + #include + } + +static void SpaceNavAdded(io_connect_t connection) + { + printf("SpaceNav added\n"); + } + +static void SpaceNavRemoved(io_connect_t connection) + { + printf("SpaceNav removed\n"); + } + +static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) + { + GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); + GHOST_NDOFManager* manager = system->getNDOFManager(); + switch (messageType) + { + case kConnexionMsgDeviceState: + { + ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + switch (s->command) + { + case kConnexionCmdHandleAxis: + manager->updateTranslation(s->axis, s->time); + manager->updateRotation(s->axis + 3, s->time); + system->notifyExternalEventProcessed(); + break; + + case kConnexionCmdHandleButtons: + manager->updateButtons(s->buttons, s->time); + system->notifyExternalEventProcessed(); + break; + } + break; + } + case kConnexionMsgPrefsChanged: + printf("prefs changed\n"); // this includes app switches + break; + case kConnexionMsgDoAction: + printf("do action\n"); // no idea what this means + // 'calibrate device' in System Prefs sends this + break; + default: + printf(" mystery event\n"); + } + } + +GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) + : GHOST_NDOFManager(sys) + { + if (available()) + { + OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); + if (error) + { + printf(" error = %d\n", error); + return; + } + + // Pascal string *and* a four-letter constant. How old-skool. + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender", + kConnexionClientModeTakeOver, kConnexionMaskAll); + + printf("client id = %d\n", m_clientID); + } + else + { + printf(" SpaceNav driver not found\n"); + // This isn't a hard error, just means the user doesn't have a SpaceNavigator. + } + } + +GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() + { + UnregisterConnexionClient(m_clientID); + CleanupConnexionHandlers(); + } + +bool GHOST_NDOFManagerCocoa::available() + { +// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// ^-- not needed since the entire framework is weak-linked + return InstallConnexionHandlers != NULL; + } -- cgit v1.2.3 From a7ba245fe39b73fc31010c647e9698dea326202b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 24 Jul 2010 11:06:08 +0000 Subject: Activated NDOF capture for Windows. Robust++ for generic NDOF manager. Removed experimental Win32 mouse and NDOF code now that good solutions are in place. Cleaned up formatting. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 16 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 994 +++++++++++++----------------- intern/ghost/intern/GHOST_SystemWin32.h | 6 +- 3 files changed, 434 insertions(+), 582 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 120805733b4..8cc4a02f51b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -15,21 +15,26 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): none yet. + * Contributor(s): Mike Erwin, July 2010. * * ***** END GPL LICENSE BLOCK ***** */ #include "GHOST_NDOFManager.h" #include "GHOST_EventNDOF.h" +#include // for memory functions +#include // for debug tracing GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) -// , m_translation((short[]){0,0,0}) -// , m_rotation((short[]){0,0,0}) , m_buttons(0) , m_atRest(true) - { } + { + // to avoid the rare situation where one triple is updated and + // the other is not, initialize them both here: + memset(m_translation, 0, sizeof(m_translation)); + memset(m_rotation, 0, sizeof(m_rotation)); + } void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) { @@ -68,7 +73,9 @@ bool GHOST_NDOFManager::sendMotionEvent() GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData(); const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually + // 350 according to their developer's guide; others recommend 500 as comfortable + // possible future enhancement // scale *= m_sensitivity; data->tx = scale * m_translation[0]; @@ -80,7 +87,6 @@ bool GHOST_NDOFManager::sendMotionEvent() data->rz = scale * m_rotation[2]; printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); - fflush(stdout); m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 14b6b16e6fb..1363e4f604b 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -27,7 +27,6 @@ */ /** - * $Id$ * Copyright (C) 2001 NaN Technologies B.V. * @author Maarten Gribnau @@ -47,28 +46,12 @@ #endif #endif -/* - * According to the docs the mouse wheel message is supported from windows 98 - * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the - * wheel detent value are undefined. - - [mce] able to remove this too? - -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A -#endif // WM_MOUSEWHEEL -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 // Value for rolling one detent, (old convention! MS changed it) -#endif // WHEEL_DELTA - */ - #include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" #include "GHOST_EventKey.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" #include "GHOST_TimerTask.h" #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" @@ -130,13 +113,7 @@ GHOST_SystemWin32::GHOST_SystemWin32() // register for RawInput devices RAWINPUTDEVICE devices[1]; -/* - // standard HID mouse - devices[0].usUsagePage = 0x01; - devices[0].usUsage = 0x02; - devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages - devices[0].hwndTarget = NULL; -*/ + // multi-axis mouse (SpaceNavigator) devices[0].usUsagePage = 0x01; devices[0].usUsage = 0x08; @@ -396,6 +373,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess GHOST_SystemWin32::exit() { + // [mce] since this duplicates its super, why bother? return GHOST_System::exit(); } @@ -522,15 +500,10 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, } -GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y) +GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x_screen, int y_screen) { - GHOST_TInt32 x_screen, y_screen; GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; - -// system->getCursorPosition(x_screen, y_screen); - x_screen = x; - y_screen = y; if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) { @@ -639,81 +612,10 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } -bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ) +bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window) { - GHOST_IEvent* event = NULL; bool eventSent = false; - puts("BEGIN"); - -#if 0 // now using the existing mouse button handlers, improved movement handler - if (raw.header.dwType == RIM_TYPEMOUSE) - { - USHORT const& buttonFlags = raw.data.mouse.usButtonFlags; - if (buttonFlags) - { - printf("button flags: %04X\n", buttonFlags); - - if (buttonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) - { - puts("left button down"); - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); - } - else if (buttonFlags & RI_MOUSE_LEFT_BUTTON_UP) - { - puts("left button up"); - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); - } - - if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) - { - puts("right button down"); - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); - } - else if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_UP) - { - puts("right button up"); - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); - } - - if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) - { - puts("middle button down"); - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); - } - else if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) - { - puts("middle button up"); - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); - } - - // similar for BUTTON_4 and BUTTON_5 - - if (buttonFlags & RI_MOUSE_WHEEL) - { - signed short wheelDelta = raw.data.mouse.usButtonData; - printf("wheel moved %+d\n", wheelDelta); - } - } - - int dx = raw.data.mouse.lLastX; // These might be in Mickeys, not pixels. - int dy = raw.data.mouse.lLastY; - if (dx || dy) - { - printf("mouse moved <%+d,%+d>\n", dx, dy); - x += dx; - x += dy; - event = processCursorEvent(GHOST_kEventCursorMove, window, x, y); - } - } -#endif // unused experimental mouse code - if (raw.header.dwType == RIM_TYPEHID) { // RID_DEVICE_INFO info; @@ -738,16 +640,20 @@ vendor ID No other registered devices use the c62_ space, so a simple mask will work! */ + // The NDOF manager sends button changes immediately, and *pretends* to + // send motion. Mark as 'sent' so motion will always get dispatched. + eventSent = true; + // multiple events per RAWHID? MSDN hints at this. - printf("%d events\n", raw.data.hid.dwCount); + printf("%d events\n", (int)raw.data.hid.dwCount); BYTE const* data = &raw.data.hid.bRawData; -// MinGW's definition (below) doesn't agree with MSDN reference for bRawData: -// typedef struct tagRAWHID { -// DWORD dwSizeHid; -// DWORD dwCount; -// BYTE bRawData; -// } RAWHID,*PRAWHID,*LPRAWHID; + // MinGW's definition (below) doesn't agree with MSDN reference for bRawData: + // typedef struct tagRAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? + // } RAWHID,*PRAWHID,*LPRAWHID; BYTE packetType = data[0]; switch (packetType) @@ -756,16 +662,20 @@ No other registered devices use the c62_ space, so a simple mask will work! { short t[3]; memcpy(t, data + 1, sizeof(t)); - printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); - m_ndofManager->updateTranslation(t, getMilliseconds()); + // too much noise -- disable for now + // printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + m_ndofManager->updateTranslation(t, getMilliSeconds()); + // wariness of alignment issues prevents me from saying it this way: + // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds()); + // though it probably (94.7%) works fine break; } case 2: // rotation { short r[3]; memcpy(r, data + 1, sizeof(r)); - printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); - m_ndofManager->updateRotation(r, getMilliseconds()); + // printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + m_ndofManager->updateRotation(r, getMilliSeconds()); break; } case 3: // buttons @@ -783,24 +693,11 @@ No other registered devices use the c62_ space, so a simple mask will work! } else printf(" none\n"); - m_ndofManager->updateButtons(buttons, getMilliseconds()); + m_ndofManager->updateButtons(buttons, getMilliSeconds()); break; } } } - - // assume only one event will come from this RawInput report - // test and adjust assumptions as needed! - - if (event) - { - pushEvent(event); - event = NULL; - eventSent = true; - } - - puts("END"); - return eventSent; } @@ -823,6 +720,7 @@ int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, i } // search for 'prev' point (we want only newer points) + // TODO: detect & ignore points that don't belong to our window for (int i = 1; i < n; ++i) if (morePoints[i].x == xPrev && morePoints[i].y == yPrev) { @@ -835,13 +733,14 @@ int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, i signed short x = morePoints[i].x; signed short y = morePoints[i].y; - printf("> (%d,%d)\n", x, y); - + // uncomment here and in WM_MOUSEMOVE handler to show effectiveness of hi-fi input + // printf("> (%d,%d)\n", x, y); + pushEvent(processCursorEvent(GHOST_kEventCursorMove, window, x, y)); } return n; - } // END getMoreMousePoints + } LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -901,479 +800,426 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM static int mousePosX = 0, mousePosY = 0; // track mouse position between calls - switch (msg) { - //////////////////////////////////////////////////////////////////////// - // Keyboard events, processed - //////////////////////////////////////////////////////////////////////// - case WM_KEYDOWN: - /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a - * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt - * key is not pressed. - */ - case WM_SYSKEYDOWN: - /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when - * the user presses the F10 key (which activates the menu bar) or holds down the - * alt key and then presses another key. It also occurs when no window currently - * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the - * active window. The window that receives the message can distinguish between these - * two contexts by checking the context code in the lKeyData parameter. - */ - switch (wParam) { - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - if (!m_separateLeftRightInitialized) { - // Check whether this system supports separate left and right keys - switch (wParam) { - case VK_SHIFT: - m_separateLeftRight = - (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || - (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? - true : false; - break; - case VK_CONTROL: - m_separateLeftRight = - (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || - (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? - true : false; - break; - case VK_MENU: - m_separateLeftRight = - (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || - (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? - true : false; - break; - } - m_separateLeftRightInitialized = true; - } - processModifierKeys(window); - // Bypass call to DefWindowProc - return true; - default: - event = processKeyEvent(window, true, wParam, lParam); - if (!event) { - GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") - GHOST_PRINT(msg) - GHOST_PRINT(" key ignored\n") - } - break; + switch (msg) { + //////////////////////////////////////////////////////////////////////// + // Keyboard events, processed + //////////////////////////////////////////////////////////////////////// + case WM_KEYDOWN: + /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a + * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt + * key is not pressed. + */ + case WM_SYSKEYDOWN: + /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when + * the user presses the F10 key (which activates the menu bar) or holds down the + * alt key and then presses another key. It also occurs when no window currently + * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the + * active window. The window that receives the message can distinguish between these + * two contexts by checking the context code in the lKeyData parameter. + */ + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + if (!m_separateLeftRightInitialized) { + // Check whether this system supports separate left and right keys + switch (wParam) { + case VK_SHIFT: + m_separateLeftRight = + (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || + (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? + true : false; + break; + case VK_CONTROL: + m_separateLeftRight = + (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || + (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? + true : false; + break; + case VK_MENU: + m_separateLeftRight = + (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || + (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? + true : false; + break; } + m_separateLeftRightInitialized = true; + } + processModifierKeys(window); + // Bypass call to DefWindowProc + return true; + default: + event = processKeyEvent(window, true, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } break; + } + break; - case WM_KEYUP: - case WM_SYSKEYUP: - switch (wParam) { - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - processModifierKeys(window); - // Bypass call to DefWindowProc - return true; - default: - event = processKeyEvent(window, false, wParam, lParam); - if (!event) { - GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") - GHOST_PRINT(msg) - GHOST_PRINT(" key ignored\n") - } - break; + case WM_KEYUP: + case WM_SYSKEYUP: + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + processModifierKeys(window); + // Bypass call to DefWindowProc + return true; + default: + event = processKeyEvent(window, false, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") } break; + } + break; #if 0 // this code is illustrative; no need to compile - //////////////////////////////////////////////////////////////////////// - // Keyboard events, ignored - //////////////////////////////////////////////////////////////////////// - case WM_CHAR: - /* The WM_CHAR message is posted to the window with the keyboard focus when - * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR - * contains the character code of the key that was pressed. - */ - case WM_DEADCHAR: - /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a - * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR - * specifies a character code generated by a dead key. A dead key is a key that - * generates a character, such as the umlaut (double-dot), that is combined with - * another character to form a composite character. For example, the umlaut-O - * character (Ù) is generated by typing the dead key for the umlaut character, and - * then typing the O key. - */ - case WM_SYSDEADCHAR: - /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when - * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. - * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, - * a dead key that is pressed while holding down the alt key. - */ - break; + //////////////////////////////////////////////////////////////////////// + // Keyboard events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_CHAR: + /* The WM_CHAR message is posted to the window with the keyboard focus when + * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR + * contains the character code of the key that was pressed. + */ + case WM_DEADCHAR: + /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a + * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR + * specifies a character code generated by a dead key. A dead key is a key that + * generates a character, such as the umlaut (double-dot), that is combined with + * another character to form a composite character. For example, the umlaut-O + * character (Ù) is generated by typing the dead key for the umlaut character, and + * then typing the O key. + */ + case WM_SYSDEADCHAR: + /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when + * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. + * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, + * a dead key that is pressed while holding down the alt key. + */ + break; #endif // illustrative code - //////////////////////////////////////////////////////////////////////// - // Tablet events, processed - //////////////////////////////////////////////////////////////////////// - case WT_PACKET: - puts("WT_PACKET"); - window->processWin32TabletEvent(wParam, lParam); - break; - case WT_CSRCHANGE: - case WT_PROXIMITY: - window->processWin32TabletInitEvent(); - break; + //////////////////////////////////////////////////////////////////////// + // Tablet events, processed + //////////////////////////////////////////////////////////////////////// + case WT_PACKET: + puts("WT_PACKET"); + window->processWin32TabletEvent(wParam, lParam); + break; + case WT_CSRCHANGE: + case WT_PROXIMITY: + window->processWin32TabletInitEvent(); + break; - //////////////////////////////////////////////////////////////////////// - // Mouse events, processed - //////////////////////////////////////////////////////////////////////// - case WM_LBUTTONDOWN: - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); - break; - case WM_MBUTTONDOWN: - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); - break; - case WM_RBUTTONDOWN: - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); - break; - case WM_XBUTTONDOWN: - window->registerMouseClickEvent(true); - if ((short) HIWORD(wParam) == XBUTTON1){ - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4); - }else if((short) HIWORD(wParam) == XBUTTON2){ - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5); - } - break; - case WM_LBUTTONUP: - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); - break; - case WM_MBUTTONUP: - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); - break; - case WM_RBUTTONUP: - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); - break; - case WM_XBUTTONUP: - window->registerMouseClickEvent(false); - if ((short) HIWORD(wParam) == XBUTTON1){ - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4); - }else if((short) HIWORD(wParam) == XBUTTON2){ - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); - } - break; -//#endif // replaced mouse code + //////////////////////////////////////////////////////////////////////// + // Mouse events, processed + //////////////////////////////////////////////////////////////////////// + case WM_LBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); + break; + case WM_XBUTTONDOWN: + window->registerMouseClickEvent(true); + if ((short) HIWORD(wParam) == XBUTTON1){ + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4); + }else if((short) HIWORD(wParam) == XBUTTON2){ + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5); + } + break; + case WM_LBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); + break; + case WM_XBUTTONUP: + window->registerMouseClickEvent(false); + if ((short) HIWORD(wParam) == XBUTTON1){ + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4); + }else if((short) HIWORD(wParam) == XBUTTON2){ + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); + } + break; - case WM_MOUSEMOVE: - { -// puts("WM_MOUSEMOVE"); + case WM_MOUSEMOVE: + { + // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs + int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + if (tabletTool) + puts("(from tablet)"); + else + { + int xPrev = mousePosX; + int yPrev = mousePosY; + // window coordinates are passed in via lParam + window->clientToScreen(LOWORD(lParam), HIWORD(lParam), mousePosX, mousePosY); -// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs - int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen - if (tabletTool) - puts("(from tablet)"); - else - { - // these give window coords, we need view coords -// mousePosX = LOWORD(lParam); -// mousePosY = HIWORD(lParam); -// window->clientToScreen(mousePosX, mousePosY, mousePosX, mousePosY); - - int xPrev = mousePosX; - int yPrev = mousePosY; - window->clientToScreen(LOWORD(lParam), HIWORD(lParam), mousePosX, mousePosY); - // if (m_input_fidelity_hint == HI_FI) // can't access hint from static function - - putchar('\n'); - - if (m_input_fidelity_hint == HI_FI) - { - /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); - // printf("%d more mouse points found\n", n); - } - - printf(" (%d,%d)\n", mousePosX, mousePosY); - - event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); - } - break; + // putchar('\n'); + + if (m_input_fidelity_hint == HI_FI) + { + /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // printf("%d more mouse points found\n", n); } - case WM_INPUT: - puts("WM_INPUT"); -{ -/* - UINT dwSize; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); - LPBYTE lpb = new BYTE[dwSize]; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); - RAWINPUT* raw = (RAWINPUT*)lpb; -*/ + // uncomment here and in getMoreMousePoints to show effectiveness of hi-fi input + // printf(" (%d,%d)\n", mousePosX, mousePosY); - RAWINPUT raw; - RAWINPUT* raw_ptr = &raw; - UINT rawSize = sizeof(RAWINPUT); -// UINT bufferSize = rawSize; - - puts("processing first event:"); - // I don't know if this is needed. Can we get by with just GetRawInputBuffer? - // Thought some mouse events were missing, so I put this in to be cautious. - // Test and remove if redundant. [mce] - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); - eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); - DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); - -// GetRawInputBuffer(NULL, &bufferSize, sizeof(RAWINPUTHEADER)); -// UINT n = bufferSize / rawSize; -// printf("allocating %d bytes (room for %d events)\n", bufferSize, n); - - RAWINPUT rawBuffer[10];// = new RAWINPUT[n]; - rawSize *= 10; - while (true) - { - int n = GetRawInputBuffer(rawBuffer, &rawSize, sizeof(RAWINPUTHEADER)); - if (n == -1) - { - printf(" error %d\n", (int) GetLastError()); - break; - } - else if (n == 0) - { - //puts("no more events"); - putchar('\n'); + event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); + } break; } - else + + case WM_INPUT: { - printf("processing %d more events:\n", n); - for (int i = 0; i < n; ++i) - { - RAWINPUT const& raw = rawBuffer[i]; - eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); - } + puts("WM_INPUT"); - // clear processed events from the queue - DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); - } - } // inf. loop -} - break; - case WM_MOUSEWHEEL: - puts("WM_MOUSEWHEEL"); - /* The WM_MOUSEWHEEL message is sent to the focus window - * when the mouse wheel is rotated. The DefWindowProc - * function propagates the message to the window's parent. - * There should be no internal forwarding of the message, - * since DefWindowProc propagates it up the parent chain - * until it finds a window that processes it. - */ - event = processWheelEvent(window, wParam, lParam); + #define RAWCOUNT 10 + // just a guess that we'll receive up to 10 event reports + // the following code fetches all available, 10 at a time + RAWINPUT rawBuffer[RAWCOUNT]; + + while (true) + { + UINT rawSize = sizeof(rawBuffer); + int n = GetRawInputBuffer(rawBuffer, &rawSize, sizeof(RAWINPUTHEADER)); + if (n == -1) + { + printf(" error %d\n", (int) GetLastError()); break; - case WM_SETCURSOR: - /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor - * to move within a window and mouse input is not captured. - * This means we have to set the cursor shape every time the mouse moves! - * The DefWindowProc function uses this message to set the cursor to an - * arrow if it is not in the client area. - */ - if (LOWORD(lParam) == HTCLIENT) { - // Load the current cursor - window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); - // Bypass call to DefWindowProc - return 0; - } - else { - // Outside of client area show standard cursor - window->loadCursor(true, GHOST_kStandardCursorDefault); } + else if (n == 0) + { + putchar('\n'); break; + } + else + { + printf("processing %d events:\n", n); + for (int i = 0; i < n; ++i) + { + RAWINPUT const& raw = rawBuffer[i]; + eventSent |= processRawInput(raw, window); + } + + // clear processed events from the queue + DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); + } + } + break; + } + case WM_MOUSEWHEEL: + puts("WM_MOUSEWHEEL"); + /* The WM_MOUSEWHEEL message is sent to the focus window + * when the mouse wheel is rotated. The DefWindowProc + * function propagates the message to the window's parent. + * There should be no internal forwarding of the message, + * since DefWindowProc propagates it up the parent chain + * until it finds a window that processes it. + */ + event = processWheelEvent(window, wParam, lParam); + break; + case WM_SETCURSOR: + /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor + * to move within a window and mouse input is not captured. + * This means we have to set the cursor shape every time the mouse moves! + * The DefWindowProc function uses this message to set the cursor to an + * arrow if it is not in the client area. + */ + if (LOWORD(lParam) == HTCLIENT) { + // Load the current cursor + window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); + // Bypass call to DefWindowProc + return 0; + } + else { + // Outside of client area show standard cursor + window->loadCursor(true, GHOST_kStandardCursorDefault); + } + break; #if 0 // this code is illustrative; no need to compile - //////////////////////////////////////////////////////////////////////// - // Mouse events, ignored - //////////////////////////////////////////////////////////////////////// - case WM_NCMOUSEMOVE: - /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved - * within the nonclient area of the window. This message is posted to the window - * that contains the cursor. If a window has captured the mouse, this message is not posted. - */ - case WM_NCHITTEST: - /* The WM_NCHITTEST message is sent to a window when the cursor moves, or - * when a mouse button is pressed or released. If the mouse is not captured, - * the message is sent to the window beneath the cursor. Otherwise, the message - * is sent to the window that has captured the mouse. - */ - break; + //////////////////////////////////////////////////////////////////////// + // Mouse events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_NCMOUSEMOVE: + /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved + * within the nonclient area of the window. This message is posted to the window + * that contains the cursor. If a window has captured the mouse, this message is not posted. + */ + case WM_NCHITTEST: + /* The WM_NCHITTEST message is sent to a window when the cursor moves, or + * when a mouse button is pressed or released. If the mouse is not captured, + * the message is sent to the window beneath the cursor. Otherwise, the message + * is sent to the window that has captured the mouse. + */ + break; #endif // illustrative code - //////////////////////////////////////////////////////////////////////// - // Window events, processed - //////////////////////////////////////////////////////////////////////// - case WM_CLOSE: - /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */ - event = processWindowEvent(GHOST_kEventWindowClose, window); - break; - case WM_ACTIVATE: - /* The WM_ACTIVATE message is sent to both the window being activated and the window being - * deactivated. If the windows use the same input queue, the message is sent synchronously, - * first to the window procedure of the top-level window being deactivated, then to the window - * procedure of the top-level window being activated. If the windows use different input queues, - * the message is sent asynchronously, so the window is activated immediately. - */ - event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); - break; - case WM_PAINT: - /* An application sends the WM_PAINT message when the system or another application - * makes a request to paint a portion of an application's window. The message is sent - * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage - * function when the application obtains a WM_PAINT message by using the GetMessage or - * PeekMessage function. - */ - event = processWindowEvent(GHOST_kEventWindowUpdate, window); - break; - case WM_GETMINMAXINFO: - /* The WM_GETMINMAXINFO message is sent to a window when the size or - * position of the window is about to change. An application can use - * this message to override the window's default maximized size and - * position, or its default minimum or maximum tracking size. - */ - processMinMaxInfo((MINMAXINFO *) lParam); - /* Let DefWindowProc handle it. */ - break; - case WM_SIZE: - /* The WM_SIZE message is sent to a window after its size has changed. - * The WM_SIZE and WM_MOVE messages are not sent if an application handles the - * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient - * to perform any move or size change processing during the WM_WINDOWPOSCHANGED - * message without calling DefWindowProc. - */ - event = processWindowEvent(GHOST_kEventWindowSize, window); - break; - case WM_CAPTURECHANGED: - window->lostMouseCapture(); - break; - case WM_MOVING: - /* The WM_MOVING message is sent to a window that the user is moving. By processing - * this message, an application can monitor the size and position of the drag rectangle - * and, if needed, change its size or position. - */ - case WM_MOVE: - /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the - * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient - * to perform any move or size change processing during the WM_WINDOWPOSCHANGED - * message without calling DefWindowProc. - */ - event = processWindowEvent(GHOST_kEventWindowMove, window); - break; + //////////////////////////////////////////////////////////////////////// + // Window events, processed + //////////////////////////////////////////////////////////////////////// + case WM_CLOSE: + /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */ + event = processWindowEvent(GHOST_kEventWindowClose, window); + break; + case WM_ACTIVATE: + /* The WM_ACTIVATE message is sent to both the window being activated and the window being + * deactivated. If the windows use the same input queue, the message is sent synchronously, + * first to the window procedure of the top-level window being deactivated, then to the window + * procedure of the top-level window being activated. If the windows use different input queues, + * the message is sent asynchronously, so the window is activated immediately. + */ + event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); + break; + case WM_PAINT: + /* An application sends the WM_PAINT message when the system or another application + * makes a request to paint a portion of an application's window. The message is sent + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * function when the application obtains a WM_PAINT message by using the GetMessage or + * PeekMessage function. + */ + event = processWindowEvent(GHOST_kEventWindowUpdate, window); + break; + case WM_GETMINMAXINFO: + /* The WM_GETMINMAXINFO message is sent to a window when the size or + * position of the window is about to change. An application can use + * this message to override the window's default maximized size and + * position, or its default minimum or maximum tracking size. + */ + processMinMaxInfo((MINMAXINFO *) lParam); + /* Let DefWindowProc handle it. */ + break; + case WM_SIZE: + /* The WM_SIZE message is sent to a window after its size has changed. + * The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + event = processWindowEvent(GHOST_kEventWindowSize, window); + break; + case WM_CAPTURECHANGED: + window->lostMouseCapture(); + break; + case WM_MOVING: + /* The WM_MOVING message is sent to a window that the user is moving. By processing + * this message, an application can monitor the size and position of the drag rectangle + * and, if needed, change its size or position. + */ + case WM_MOVE: + /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + event = processWindowEvent(GHOST_kEventWindowMove, window); + break; #if 0 // this code is illustrative; no need to compile - //////////////////////////////////////////////////////////////////////// - // Window events, ignored - //////////////////////////////////////////////////////////////////////// - case WM_WINDOWPOSCHANGED: - /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place - * in the Z order has changed as a result of a call to the SetWindowPos function or - * another window-management function. - * The WM_SIZE and WM_MOVE messages are not sent if an application handles the - * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient - * to perform any move or size change processing during the WM_WINDOWPOSCHANGED - * message without calling DefWindowProc. - */ - case WM_ERASEBKGND: - /* An application sends the WM_ERASEBKGND message when the window background must be - * erased (for example, when a window is resized). The message is sent to prepare an - * invalidated portion of a window for painting. - */ - case WM_NCPAINT: - /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */ - case WM_NCACTIVATE: - /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed - * to indicate an active or inactive state. - */ - case WM_DESTROY: - /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window - * procedure of the window being destroyed after the window is removed from the screen. - * This message is sent first to the window being destroyed and then to the child windows - * (if any) as they are destroyed. During the processing of the message, it can be assumed - * that all child windows still exist. - */ - case WM_NCDESTROY: - /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The - * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY - * message. WM_DESTROY is used to free the allocated memory object associated with the window. - */ - case WM_KILLFOCUS: - /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */ - case WM_SHOWWINDOW: - /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */ - case WM_WINDOWPOSCHANGING: - /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in - * the Z order is about to change as a result of a call to the SetWindowPos function or - * another window-management function. - */ - case WM_SETFOCUS: - /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */ - case WM_ENTERSIZEMOVE: - /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving - * or sizing modal loop. The window enters the moving or sizing modal loop when the user - * clicks the window's title bar or sizing border, or when the window passes the - * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the - * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when - * DefWindowProc returns. - */ - break; - - //////////////////////////////////////////////////////////////////////// - // Other events - //////////////////////////////////////////////////////////////////////// - case WM_GETTEXT: - /* An application sends a WM_GETTEXT message to copy the text that - * corresponds to a window into a buffer provided by the caller. - */ - case WM_ACTIVATEAPP: - /* The WM_ACTIVATEAPP message is sent when a window belonging to a - * different application than the active window is about to be activated. - * The message is sent to the application whose window is being activated - * and to the application whose window is being deactivated. - */ - case WM_TIMER: - /* The WIN32 docs say: - * The WM_TIMER message is posted to the installing thread's message queue - * when a timer expires. You can process the message by providing a WM_TIMER - * case in the window procedure. Otherwise, the default window procedure will - * call the TimerProc callback function specified in the call to the SetTimer - * function used to install the timer. - * - * In GHOST, we let DefWindowProc call the timer callback. - */ - break; + //////////////////////////////////////////////////////////////////////// + // Window events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_WINDOWPOSCHANGED: + /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place + * in the Z order has changed as a result of a call to the SetWindowPos function or + * another window-management function. + * The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + case WM_ERASEBKGND: + /* An application sends the WM_ERASEBKGND message when the window background must be + * erased (for example, when a window is resized). The message is sent to prepare an + * invalidated portion of a window for painting. + */ + case WM_NCPAINT: + /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */ + case WM_NCACTIVATE: + /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed + * to indicate an active or inactive state. + */ + case WM_DESTROY: + /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window + * procedure of the window being destroyed after the window is removed from the screen. + * This message is sent first to the window being destroyed and then to the child windows + * (if any) as they are destroyed. During the processing of the message, it can be assumed + * that all child windows still exist. + */ + case WM_NCDESTROY: + /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The + * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY + * message. WM_DESTROY is used to free the allocated memory object associated with the window. + */ + case WM_KILLFOCUS: + /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */ + case WM_SHOWWINDOW: + /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */ + case WM_WINDOWPOSCHANGING: + /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in + * the Z order is about to change as a result of a call to the SetWindowPos function or + * another window-management function. + */ + case WM_SETFOCUS: + /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */ + case WM_ENTERSIZEMOVE: + /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving + * or sizing modal loop. The window enters the moving or sizing modal loop when the user + * clicks the window's title bar or sizing border, or when the window passes the + * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the + * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when + * DefWindowProc returns. + */ + break; + + //////////////////////////////////////////////////////////////////////// + // Other events + //////////////////////////////////////////////////////////////////////// + case WM_GETTEXT: + /* An application sends a WM_GETTEXT message to copy the text that + * corresponds to a window into a buffer provided by the caller. + */ + case WM_ACTIVATEAPP: + /* The WM_ACTIVATEAPP message is sent when a window belonging to a + * different application than the active window is about to be activated. + * The message is sent to the application whose window is being activated + * and to the application whose window is being deactivated. + */ + case WM_TIMER: + /* The WIN32 docs say: + * The WM_TIMER message is posted to the installing thread's message queue + * when a timer expires. You can process the message by providing a WM_TIMER + * case in the window procedure. Otherwise, the default window procedure will + * call the TimerProc callback function specified in the call to the SetTimer + * function used to install the timer. + * + * In GHOST, we let DefWindowProc call the timer callback. + */ + break; #endif // illustrative code - -#if 0 // this is part of the 'old' NDOF system; new one coming soon! - case WM_BLND_NDOF_AXIS: - { - GHOST_TEventNDOFData ndofdata; - m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - m_eventManager-> - pushEvent(new GHOST_EventNDOF( - getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, ndofdata)); - } - break; - case WM_BLND_NDOF_BTN: - { - GHOST_TEventNDOFData ndofdata; - m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - m_eventManager-> - pushEvent(new GHOST_EventNDOF( - getMilliSeconds(), - GHOST_kEventNDOFButton, - window, ndofdata)); - } - break; -#endif // old NDOF - } + } if (!eventSent) if (event) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 8fae4d6ba78..abf6886deea 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -304,10 +304,9 @@ protected: * Creates and sends mouse or multi-axis events. * @param raw a single RawInput structure * @param window The window receiving the event (the active window). - * @param x,y current mouse coordinates, which may be updated by this function * @return Whether any events (possibly more than one) were created and sent. */ - bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ); + bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window); /** * Creates and sends mouse events for mouse movements "in between" WM_MOUSEMOVEs. @@ -333,10 +332,11 @@ protected: /** * Windows call back routine for our window class. + * This handles general errors, then passes control to handleEvent. */ static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - // non-static version of WndProc + /** Non-static version of WndProc. */ bool handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam); /** The current state of the modifier keys. */ -- cgit v1.2.3 From b0193772dae9cbb9a52cd18355393b16a6e5001c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 25 Jul 2010 08:38:13 +0000 Subject: removing Mac C++ file (contents same as Obj-C++ file), since TortoiseSVN's 'rename' forgot to do it --- intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 113 ------------------------- 1 file changed, 113 deletions(-) delete mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp deleted file mode 100644 index c4a8a2f1831..00000000000 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "GHOST_NDOFManagerCocoa.h" -#include "GHOST_SystemCocoa.h" - -extern "C" { - #include <3DconnexionClient/ConnexionClientAPI.h> - #include - } - -static void SpaceNavAdded(io_connect_t connection) - { - printf("SpaceNav added\n"); - } - -static void SpaceNavRemoved(io_connect_t connection) - { - printf("SpaceNav removed\n"); - } - -static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) - { - GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); - GHOST_NDOFManager* manager = system->getNDOFManager(); - switch (messageType) - { - case kConnexionMsgDeviceState: - { - ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; - switch (s->command) - { - case kConnexionCmdHandleAxis: - manager->updateTranslation(s->axis, s->time); - manager->updateRotation(s->axis + 3, s->time); - system->notifyExternalEventProcessed(); - break; - - case kConnexionCmdHandleButtons: - manager->updateButtons(s->buttons, s->time); - system->notifyExternalEventProcessed(); - break; - } - break; - } - case kConnexionMsgPrefsChanged: - printf("prefs changed\n"); // this includes app switches - break; - case kConnexionMsgDoAction: - printf("do action\n"); // no idea what this means - // 'calibrate device' in System Prefs sends this - break; - default: - printf(" mystery event\n"); - } - } - -GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) - : GHOST_NDOFManager(sys) - { - if (available()) - { - OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); - if (error) - { - printf(" error = %d\n", error); - return; - } - - // Pascal string *and* a four-letter constant. How old-skool. - m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender", - kConnexionClientModeTakeOver, kConnexionMaskAll); - - printf("client id = %d\n", m_clientID); - } - else - { - printf(" SpaceNav driver not found\n"); - // This isn't a hard error, just means the user doesn't have a SpaceNavigator. - } - } - -GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() - { - UnregisterConnexionClient(m_clientID); - CleanupConnexionHandlers(); - } - -bool GHOST_NDOFManagerCocoa::available() - { -// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); -// ^-- not needed since the entire framework is weak-linked - return InstallConnexionHandlers != NULL; - } -- cgit v1.2.3 From f399481251a4d375a494517925c64b3b3c6db7e8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 7 Aug 2010 10:57:15 +0000 Subject: SpaceNav turntable and fit in 3D view. Tablet data rides with cursor/button events (incomplete! Mac-only for now). Grease pencil works better with pen. --- intern/ghost/GHOST_Types.h | 100 ++++++++++------------- intern/ghost/intern/GHOST_EventButton.h | 2 +- intern/ghost/intern/GHOST_EventCursor.h | 1 + intern/ghost/intern/GHOST_EventManager.cpp | 4 +- intern/ghost/intern/GHOST_EventNDOF.h | 48 ++++++------ intern/ghost/intern/GHOST_NDOFManager.cpp | 41 ++++++++-- intern/ghost/intern/GHOST_NDOFManager.h | 4 + intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 10 ++- intern/ghost/intern/GHOST_SystemCocoa.h | 16 ++-- intern/ghost/intern/GHOST_SystemCocoa.mm | 62 ++++++++++++--- intern/ghost/intern/GHOST_WindowCocoa.h | 8 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 109 +++++++++++++------------- 12 files changed, 225 insertions(+), 180 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 66bfa0e469f..952c1860dc1 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -29,27 +29,22 @@ #ifndef _GHOST_TYPES_H_ #define _GHOST_TYPES_H_ -typedef char GHOST_TInt8; -typedef unsigned char GHOST_TUns8; -typedef short GHOST_TInt16; -typedef unsigned short GHOST_TUns16; -typedef int GHOST_TInt32; -typedef unsigned int GHOST_TUns32; - -#ifdef WIN32 -#define WM_BLND_NDOF_AXIS WM_USER + 1 -#define WM_BLND_NDOF_BTN WM_USER + 2 -#endif +typedef char GHOST_TInt8; +typedef unsigned char GHOST_TUns8; +typedef short GHOST_TInt16; +typedef unsigned short GHOST_TUns16; +typedef int GHOST_TInt32; +typedef unsigned int GHOST_TUns32; #if defined(WIN32) && !defined(FREE_WINDOWS) -typedef __int64 GHOST_TInt64; -typedef unsigned __int64 GHOST_TUns64; + typedef __int64 GHOST_TInt64; + typedef unsigned __int64 GHOST_TUns64; #else -typedef long long GHOST_TInt64; -typedef unsigned long long GHOST_TUns64; + typedef long long GHOST_TInt64; + typedef unsigned long long GHOST_TUns64; #endif -typedef void* GHOST_TUserDataPtr; +typedef void* GHOST_TUserDataPtr; typedef enum { @@ -154,8 +149,7 @@ typedef enum { GHOST_kEventTrackpad, /// Trackpad event GHOST_kEventNDOFMotion, /// N degree of freedom device motion event - GHOST_kEventNDOFButtonDown,/// N degree of freedom device button events - GHOST_kEventNDOFButtonUp, + GHOST_kEventNDOFButton, GHOST_kEventKeyDown, GHOST_kEventKeyUp, @@ -276,7 +270,6 @@ typedef enum { GHOST_kKeyRightBracket = ']', GHOST_kKeyBackslash = 0x5C, GHOST_kKeyAccentGrave = '`', - GHOST_kKeyLeftShift = 0x100, GHOST_kKeyRightShift, @@ -284,8 +277,8 @@ typedef enum { GHOST_kKeyRightControl, GHOST_kKeyLeftAlt, GHOST_kKeyRightAlt, - GHOST_kKeyCommand, // APPLE only! - GHOST_kKeyGrLess , // German PC only! + GHOST_kKeyCommand, // APPLE only! + GHOST_kKeyGrLess, // German PC only! GHOST_kKeyCapsLock, GHOST_kKeyNumLock, @@ -365,11 +358,17 @@ typedef struct { GHOST_TInt32 x; /** The y-coordinate of the cursor position. */ GHOST_TInt32 y; + + GHOST_TabletData tablet; + } GHOST_TEventCursorData; typedef struct { /** The mask of the mouse button. */ GHOST_TButtonMask button; + + GHOST_TabletData tablet; + } GHOST_TEventButtonData; typedef struct { @@ -384,7 +383,6 @@ typedef enum { GHOST_kTrackpadEventSwipe, /* Reserved, not used for now */ GHOST_kTrackpadEventMagnify } GHOST_TTrackpadEventSubTypes; - typedef struct { /** The event subtype */ @@ -423,40 +421,23 @@ typedef struct { GHOST_TUns8 **strings; } GHOST_TStringArray; - -/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */ -/* as all USB device controls are likely to use ints, this is also more future proof */ -//typedef struct { -// /** N-degree of freedom device data */ -// float tx, ty, tz; /** -x left, +y up, +z forward */ -// float rx, ry, rz; -// float dt; -//} GHOST_TEventNDOFData; - -// typedef struct { -// /** N-degree of freedom device data v2*/ -// int changed; -// GHOST_TUns64 client; -// GHOST_TUns64 address; -// GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ -// GHOST_TInt16 rx, ry, rz; -// GHOST_TInt16 buttons; -// GHOST_TUns64 time; -// GHOST_TUns64 delta; -// } GHOST_TEventNDOFData; - typedef struct { /** N-degree of freedom device data v3 [GSoC 2010]*/ + /* Each component normally ranges from -1 to +1, but can exceed that. */ + float tx, ty, tz; /* translation: -x left, +y forward, -z up */ + float rx, ry, rz; /* rotation: + axis = (rx,ry,rz).normalized + amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] */ + float dt; // time since previous NDOF Motion event (or zero if this is the first) - // Fairly close to raw device data. - // Each component normally ranges from -1 to +1, but can exceed that. - // rot axis = (rx,ry,rz).normalized - // rot amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] +} GHOST_TEventNDOFMotionData; - float tx, ty, tz; /** -x left, +y forward, -z up */ - float rx, ry, rz; -} GHOST_TEventNDOFData; +typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction; // good for mouse or other buttons too, hmmm? +typedef struct { + GHOST_TButtonAction action; + short button; +} GHOST_TEventNDOFButtonData; typedef struct { /** The key code. */ @@ -478,13 +459,13 @@ typedef struct { #ifdef _WIN32 -typedef long GHOST_TEmbedderWindowID; + typedef long GHOST_TEmbedderWindowID; #endif // _WIN32 #ifndef _WIN32 -// I can't use "Window" from "" because it conflits with Window defined in winlay.h -typedef int GHOST_TEmbedderWindowID; -#endif // _WIN32 + // I can't use "Window" from "" because it conflits with Window defined in winlay.h + typedef int GHOST_TEmbedderWindowID; +#endif /** * A timer task callback routine. @@ -492,12 +473,11 @@ typedef int GHOST_TEmbedderWindowID; * @param time The current time. */ #ifdef __cplusplus -class GHOST_ITimerTask; -typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time); + class GHOST_ITimerTask; + typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time); #else -struct GHOST_TimerTaskHandle__; -typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time); + struct GHOST_TimerTaskHandle__; + typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time); #endif #endif // _GHOST_TYPES_H_ - diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h index d8631ea47e4..b33095a8efe 100644 --- a/intern/ghost/intern/GHOST_EventButton.h +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -55,6 +55,7 @@ public: : GHOST_Event(time, type, window) { m_buttonEventData.button = button; + m_buttonEventData.tablet.Active = GHOST_kTabletModeNone; m_data = &m_buttonEventData; } @@ -64,4 +65,3 @@ protected: }; #endif // _GHOST_EVENT_BUTTON_H_ - diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h index 5390e3b2253..e324cf6e9fa 100644 --- a/intern/ghost/intern/GHOST_EventCursor.h +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -55,6 +55,7 @@ public: { m_cursorEventData.x = x; m_cursorEventData.y = y; + m_cursorEventData.tablet.Active = GHOST_kTabletModeNone; m_data = &m_cursorEventData; } diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index bc0d7ada74d..b566c1e38c8 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -110,7 +110,7 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) { // [mce] this variant switches the "handled" flag to work as described in the header - // it also stops after the first consumer has handled the event + // it also stops after the first consumer has handled the event (no it doesn't) bool handled = false; if (event) { TConsumerVector::iterator iter; @@ -322,7 +322,7 @@ GHOST_IEvent* GHOST_EventManager::popEvent() void GHOST_EventManager::disposeEvents() { - while (m_events.size() > 0) { + while (!m_events.empty()) { GHOST_ASSERT(m_events[0], "invalid event"); delete m_events[0]; m_events.pop_front(); diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index c5d35126f01..394aff0493f 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -28,33 +28,31 @@ class GHOST_EventNDOFMotion : public GHOST_Event -{ -protected: - GHOST_TEventNDOFData m_axisData; - -public: - GHOST_EventNDOFMotion(GHOST_TUns64 time) - : GHOST_Event(time, GHOST_kEventNDOFMotion, NULL) -// , m_data(&m_axisData) - { - m_data = &m_axisData; - } -}; + { + protected: + GHOST_TEventNDOFMotionData m_axisData; + + public: + GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFMotion, window) + { + m_data = &m_axisData; + } + }; + class GHOST_EventNDOFButton : public GHOST_Event -{ -protected: - GHOST_TUns16 m_buttonNumber; - -public: - GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_TUns16 buttonNumber, GHOST_TEventType upOrDown) - : GHOST_Event(time, upOrDown, NULL) - , m_buttonNumber(buttonNumber) -// , m_data(&m_buttonNumber) - { - m_data = &m_buttonNumber; - } -}; + { + protected: + GHOST_TEventNDOFButtonData m_buttonData; + + public: + GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFButton, window) + { + m_data = &m_buttonData; + } + }; #endif // _GHOST_EVENT_NDOF_H_ diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 8cc4a02f51b..1c00e991520 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -22,12 +22,15 @@ #include "GHOST_NDOFManager.h" #include "GHOST_EventNDOF.h" +#include "GHOST_WindowManager.h" #include // for memory functions #include // for debug tracing GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) , m_buttons(0) + , m_motionTime(1000) // one full second (operators should filter out such large time deltas) + , m_prevMotionTime(0) , m_atRest(true) { // to avoid the rare situation where one triple is updated and @@ -52,13 +55,28 @@ void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) { + GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); + GHOST_IWindow* window = system->getWindowManager()->getActiveWindow(); + unsigned short diff = m_buttons ^ buttons; + for (int i = 0; i < 16; ++i) { unsigned short mask = 1 << i; + if (diff & mask) - m_system.pushEvent(new GHOST_EventNDOFButton(time, i + 1, - (buttons & mask) ? GHOST_kEventNDOFButtonDown : GHOST_kEventNDOFButtonUp)); + { + GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); + GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); + + data->action = (buttons & mask) ? GHOST_kPress : GHOST_kRelease; +// data->pressed = buttons & mask; + data->button = i + 1; + +// printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); + + m_system.pushEvent(event); + } } m_buttons = buttons; @@ -69,8 +87,11 @@ bool GHOST_NDOFManager::sendMotionEvent() if (m_atRest) return false; - GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime); - GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData(); + GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); + GHOST_IWindow* window = system->getWindowManager()->getActiveWindow(); + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); + GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually // 350 according to their developer's guide; others recommend 500 as comfortable @@ -78,7 +99,7 @@ bool GHOST_NDOFManager::sendMotionEvent() // possible future enhancement // scale *= m_sensitivity; - data->tx = scale * m_translation[0]; + data->tx = -scale * m_translation[0]; data->ty = scale * m_translation[1]; data->tz = scale * m_translation[2]; @@ -86,13 +107,19 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; - printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + printf("dt = %d ms\n", (int)(m_motionTime - m_prevMotionTime)); + + m_prevMotionTime = m_motionTime; + +// printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); m_system.pushEvent(event); // 'at rest' test goes at the end so that the first 'rest' event gets sent m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; - + return true; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 035f9f22f0a..9d0bfa3b789 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -55,7 +55,11 @@ protected: unsigned short m_buttons; GHOST_TUns64 m_motionTime; + GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent bool m_atRest; + + void updateMotionTime(GHOST_TUns64 t); + void resetMotion(); }; diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index c4a8a2f1831..b29cbb6d0ce 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -47,16 +47,20 @@ static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void * case kConnexionMsgDeviceState: { ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + + GHOST_TUns64 now = system->getMilliSeconds(); + switch (s->command) { case kConnexionCmdHandleAxis: - manager->updateTranslation(s->axis, s->time); - manager->updateRotation(s->axis + 3, s->time); +// manager->updateTranslation(s->axis, s->time); + manager->updateTranslation(s->axis, now); + manager->updateRotation(s->axis + 3, now); system->notifyExternalEventProcessed(); break; case kConnexionCmdHandleButtons: - manager->updateButtons(s->buttons, s->time); + manager->updateButtons(s->buttons, now); system->notifyExternalEventProcessed(); break; } diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 97b9cb2804d..c84c69707ad 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -35,11 +35,8 @@ #define _GHOST_SYSTEM_COCOA_H_ #ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ - -//#define __CARBONSOUND__ - + #error Apple OSX only! +#endif #include "GHOST_System.h" @@ -266,6 +263,11 @@ protected: * @return Indication whether the event was handled. */ GHOST_TSuccess handleTabletEvent(void *eventPtr); + + /** + * Helps handleTabletEvent function. + */ + void fillTabletData(GHOST_TabletData& tablet, void* event_ptr); /** * Handles a tablet proximity event. Sets pen or mouse ID for later events. @@ -307,7 +309,8 @@ protected: /** Start time at initialization. */ GHOST_TUns64 m_start_time; - + double m_start_time_2; + /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; @@ -336,4 +339,3 @@ protected: }; #endif // _GHOST_SYSTEM_COCOA_H_ - diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index b8eee5ed7e0..b17f7ab7c2e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -568,6 +568,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl(mib, 2, &boottime, &len, NULL, 0); m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000)); + m_start_time_2 = CFAbsoluteTimeGetCurrent(); + //Detect multitouch trackpad mib[0] = CTL_HW; mib[1] = HW_MODEL; @@ -675,6 +677,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init() GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const { +/* //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime]) struct timeval currentTime; @@ -682,6 +685,10 @@ GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const //Return timestamp of system uptime return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time); +*/ + + double now = CFAbsoluteTimeGetCurrent(); + return 1000 * (now - m_start_time_2); } @@ -1392,7 +1399,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) return GHOST_kFailure; } - GHOST_TabletData& ct = window->GetCocoaTabletData(); +// don't involve the window! +// GHOST_TabletData& ct = window->GetCocoaTabletData(); GHOST_TTabletMode active_tool; int* tool_id_ptr; @@ -1423,27 +1431,43 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) printf("entering\n"); *tool_id_ptr = [event deviceID]; - ct.Active = active_tool; - ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0; - ct.Xtilt = 0; - ct.Ytilt = 0; + m_tablet_pen_mode = active_tool; + +// ct.Active = active_tool; +// ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0; +// ct.Xtilt = 0; +// ct.Ytilt = 0; // this is a good place to remember the tool's capabilities - // (later though, after tablet mouse is fixed and (not) coalescing is in place) } else { printf("leaving\n"); *tool_id_ptr = TOOL_ID_NONE; - ct.Active = GHOST_kTabletModeNone; - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; + m_tablet_pen_mode = GHOST_kTabletModeNone; + +// ct.Active = GHOST_kTabletModeNone; +// ct.Pressure = 0; +// ct.Xtilt = 0; +// ct.Ytilt = 0; } return GHOST_kSuccess; } +void GHOST_SystemCocoa::fillTabletData(GHOST_TabletData& tablet, void* event_ptr) + { + NSEvent* event = (NSEvent*)event_ptr; + NSPoint tilt = [event tilt]; + + tablet.Active = m_tablet_pen_mode; + tablet.Pressure = [event pressure]; + tablet.Xtilt = tilt.x; + tablet.Ytilt = tilt.y; + + printf("> pressure = %.2f tilt = %.2f %2f\n", tablet.Pressure, tablet.Xtilt, tablet.Ytilt); + } + GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) { puts("tablet point"); @@ -1456,35 +1480,49 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) return GHOST_kFailure; } +/* + // don't involve the window! GHOST_TabletData& ct = window->GetCocoaTabletData(); ct.Pressure = [event pressure]; NSPoint tilt = [event tilt]; ct.Xtilt = tilt.x; ct.Ytilt = tilt.y; +*/ switch ([event type]) { case NSLeftMouseDown: + { if (m_input_fidelity_hint == HI_FI) { printf("hi-fi on\n"); [NSEvent setMouseCoalescingEnabled:NO]; } - pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); + GHOST_EventButton* e = new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber])); + GHOST_TEventButtonData* data = (GHOST_TEventButtonData*) e->getData(); + fillTabletData(data->tablet, event); + pushEvent(e); break; + } case NSLeftMouseUp: + { if (m_input_fidelity_hint == HI_FI) { printf("hi-fi off\n"); [NSEvent setMouseCoalescingEnabled:YES]; } + // no tablet data needed for 'pen up' pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); break; + } default: { NSPoint pos = [event locationInWindow]; - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y)); + GHOST_EventCursor* e = new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y); + GHOST_TEventCursorData* data = (GHOST_TEventCursorData*) e->getData(); + fillTabletData(data->tablet, event); + pushEvent(e); break; } } diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 7948e88e1ab..c8285547e99 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -222,11 +222,8 @@ public: const GHOST_TabletData* GetTabletData() - { return &m_tablet; } + { return NULL; } - GHOST_TabletData& GetCocoaTabletData() - { return m_tablet; } - /** * Sets the progress bar value displayed in the window/application icon * @param progress The progress % (0.0 to 1.0) @@ -300,9 +297,6 @@ protected: static NSOpenGLContext *s_firstOpenGLcontext; NSCursor* m_customCursor; - - GHOST_TabletData m_tablet; }; #endif // _GHOST_WINDOW_COCOA_H_ - diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index a97f7621bb0..23535ba2f59 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -39,7 +39,7 @@ #include */ - + #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" #include "GHOST_Debug.h" @@ -161,12 +161,12 @@ extern "C" { { NSPoint mouseLocation = [sender draggingLocation]; NSPasteboard *draggingPBoard = [sender draggingPasteboard]; - + if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeBitmap; else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeFilenames; else if ([[draggingPBoard types] containsObject:NSStringPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeString; else return NSDragOperationNone; - + associatedWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); return NSDragOperationCopy; @@ -180,7 +180,7 @@ extern "C" { - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { NSPoint mouseLocation = [sender draggingLocation]; - + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; } @@ -205,7 +205,7 @@ extern "C" { NSPasteboard *draggingPBoard = [sender draggingPasteboard]; NSImage *droppedImg; id data; - + switch (m_draggedObjectType) { case GHOST_kDragnDropTypeBitmap: if([NSImage canInitWithPasteboard:draggingPBoard]) { @@ -242,7 +242,7 @@ extern "C" { - (BOOL)acceptsFirstResponder { - return YES; + return YES; } //The trick to prevent Cocoa from complaining (beeping) @@ -254,10 +254,10 @@ extern "C" { - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { NSString *chars = [theEvent charactersIgnoringModifiers]; - + if ([chars length] <1) return NO; - + //Let cocoa handle menu shortcuts switch ([chars characterAtIndex:0]) { case 'q': @@ -277,7 +277,7 @@ extern "C" { - (BOOL)isOpaque { - return YES; + return YES; } @end @@ -304,22 +304,21 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40]; NSOpenGLPixelFormat *pixelFormat = nil; int i; - + m_systemCocoa = systemCocoa; m_fullScreen = false; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - //Creates the window NSRect rect; NSSize minSize; - + rect.origin.x = left; rect.origin.y = top; rect.size.width = width; rect.size.height = height; - + m_window = [[CocoaWindow alloc] initWithContentRect:rect styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO]; @@ -327,75 +326,75 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( [pool drain]; return; } - + [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; - + //Forbid to resize the window below the blender defined minimum one minSize.width = 320; minSize.height = 240; [m_window setContentMinSize:minSize]; - + setTitle(title); - - + + // Pixel Format Attributes for the windowed NSOpenGLContext i=0; pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; - + // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer // needed for 'Draw Overlap' drawing method pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; - - + + if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; - + if (numOfAASamples>0) { // Multisample anti-aliasing pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery; } - + pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; - + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; - - + + //Fall back to no multisampling if Antialiasing init failed if (pixelFormat == nil) { i=0; pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; - + // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer // needed for 'Draw Overlap' drawing method pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway - + pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; - + if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; - + pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; - + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; - + } - + if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value GLint gli; [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0]; @@ -404,40 +403,38 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples); } } - + //Creates the OpenGL View inside the window m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; - + [pixelFormat release]; - + m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after - + [m_window setContentView:m_openGLView]; [m_window setInitialFirstResponder:m_openGLView]; - + [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window - + [m_window makeKeyAndOrderFront:nil]; - + setDrawingContextType(type); updateDrawingContext(); activateDrawingContext(); - - m_tablet.Active = GHOST_kTabletModeNone; - + CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; [m_window setDelegate:windowDelegate]; - + [m_window setAcceptsMouseMovedEvents:YES]; - + [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, NSTIFFPboardType, nil]]; - + if (state == GHOST_kWindowStateFullScreen) setState(GHOST_kWindowStateFullScreen); - + [pool drain]; } @@ -448,14 +445,14 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView release]; - + if (m_window) { [m_window close]; [[m_window delegate] release]; [m_window release]; m_window = nil; } - + //Check for other blender opened windows and make the frontmost key NSArray *windowsList = [NSApp orderedWindows]; if ([windowsList count]) { @@ -478,7 +475,7 @@ void* GHOST_WindowCocoa::getOSWindow() const void GHOST_WindowCocoa::setTitle(const STR_String& title) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithUTF8String:title]; -- cgit v1.2.3 From ced1bd9e7dd5bc3e14d7f0f5e09a7b65f3ea2be2 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 8 Aug 2010 05:08:35 +0000 Subject: Windows shell/IE #define. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 1 + intern/ghost/intern/GHOST_SystemWin32.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index cada3f68975..c1c6f874222 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -38,6 +38,7 @@ #include // for debug [mce] +#define _WIN32_IE 0x501 /* shipped before XP, so doesn't impose additional req'm'ts */ #include diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 9febe7779bc..03bf6f08df8 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -35,12 +35,12 @@ #ifndef WIN32 #error WIN32 only! -#endif // WIN32 +#endif #define _WIN32_WINNT 0x501 // require Windows XP or newer #define WIN32_LEAN_AND_MEAN #include -#include +#include // for drag-n-drop #include "GHOST_System.h" -- cgit v1.2.3 From 4bf887d4d3592e955144388305ae801040a57701 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 10 Aug 2010 09:51:22 +0000 Subject: SpaceNav works in 3D view on Windows. Cleaned up related WIP code. --- intern/ghost/GHOST_ISystem.h | 1 - intern/ghost/intern/GHOST_EventManager.cpp | 22 +++++--------- intern/ghost/intern/GHOST_EventManager.h | 35 ++++++++------------- intern/ghost/intern/GHOST_NDOFManager.cpp | 14 +++------ intern/ghost/intern/GHOST_System.cpp | 15 +++------ intern/ghost/intern/GHOST_SystemWin32.cpp | 47 ++++++++++++++++++++--------- intern/ghost/intern/GHOST_WindowManager.cpp | 2 +- 7 files changed, 65 insertions(+), 71 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index ab974508145..b759b98f0bc 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -400,4 +400,3 @@ protected: }; #endif // _GHOST_ISYSTEM_H_ - diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index b566c1e38c8..7fd3a0971a5 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -39,14 +39,9 @@ #include "GHOST_Debug.h" // for testing lo-fi -#include "GHOST_EventPrinter.h" -#include -using namespace std; - -GHOST_EventManager::GHOST_EventManager() -{ -} - +// #include "GHOST_EventPrinter.h" +// #include +// using namespace std; GHOST_EventManager::~GHOST_EventManager() { @@ -110,14 +105,12 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) { // [mce] this variant switches the "handled" flag to work as described in the header - // it also stops after the first consumer has handled the event (no it doesn't) bool handled = false; if (event) { TConsumerVector::iterator iter; for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) { if ((*iter)->processEvent(event)) { handled = true; - // break; } } } @@ -125,7 +118,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) } #if 0 // disable to test a variant -bool GHOST_EventManager::dispatchEvent_original(GHOST_IEvent* event) +bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) /* original version */ { bool handled; if (event) { @@ -190,6 +183,7 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() // cout << "\n--- lo-fi dispatch ---"; // cout << "\ndiscard:"; + while ((event = popEvent()) != NULL) { if (event->getType() == GHOST_kEventCursorMove) { // just a simple (x,y) pair, nothing much to adjust @@ -204,7 +198,7 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() if (!dispatchEvent(event)) allHandled = false; } - + // finally dispatch the single cursor update if (cursorMove) { // cout << "\nsend:"; @@ -268,7 +262,7 @@ void GHOST_EventManager::removeWindowEvents(GHOST_IWindow* window) GHOST_IEvent* event = *iter; if (event->getWindow() == window) { - GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n"); + GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n"); /* * Found an event for this window, remove it. * The iterator will become invalid. @@ -293,7 +287,7 @@ void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow* GHOST_IEvent* event = *iter; if ((event->getType() == type) && (!window || (event->getWindow() == window))) { - GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n"); + GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n"); /* * Found an event of this type for the window, remove it. * The iterator will become invalid. diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index 5071adb1bd4..c73abed2f7e 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -53,32 +53,32 @@ public: /** * Constructor. */ - GHOST_EventManager(); + GHOST_EventManager() {}; /** * Destructor. */ - virtual ~GHOST_EventManager(); + ~GHOST_EventManager(); /** * Returns the number of events currently on the stack. * @return The number of events on the stack. */ - virtual GHOST_TUns32 getNumEvents(); + GHOST_TUns32 getNumEvents(); /** * Returns the number of events of a certain type currently on the stack. * @param type The type of events to be counted. * @return The number of events on the stack of this type. */ - virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type); + GHOST_TUns32 getNumEvents(GHOST_TEventType type); /** * Return the event at the top of the stack without removal. * Do not delete the event! * @return The event at the top of the stack. */ - virtual GHOST_IEvent* peekEvent(); + GHOST_IEvent* peekEvent(); /** * Pushes an event on the stack. @@ -86,27 +86,27 @@ public: * Do not delete the event! * @param event The event to push on the stack. */ - virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event); + GHOST_TSuccess pushEvent(GHOST_IEvent* event); /** * Dispatches the given event directly, bypassing the event stack. * @return Indication as to whether any of the consumers handled the event. */ - virtual bool dispatchEvent(GHOST_IEvent* event); + bool dispatchEvent(GHOST_IEvent* event); /** * Dispatches the event at the back of the stack. * The event will be removed from the stack. * @return Indication as to whether any of the consumers handled the event. */ - virtual bool dispatchEvent(); + bool dispatchEvent(); /** * Dispatches all the events on the stack. * The event stack will be empty afterwards. * @return Indication as to whether any of the consumers handled the events. */ - virtual bool dispatchEvents(); + bool dispatchEvents(); /** * Dispatches most events on the stack, consolidating cursor moves into a single move. @@ -115,29 +115,25 @@ public: */ bool dispatchEvents_lo_fi(); - /** * Adds a consumer to the list of event consumers. * @param consumer The consumer added to the list. * @return Indication as to whether addition has succeeded. */ - virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer); + GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer); /** * Removes a consumer from the list of event consumers. * @param consumer The consumer removed from the list. * @return Indication as to whether removal has succeeded. */ - virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer); + GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer); /** * Removes all events for a window from the stack. * @param window The window to remove events for. */ - virtual void - removeWindowEvents( - GHOST_IWindow* window - ); + void removeWindowEvents(GHOST_IWindow* window); /** * Removes all events of a certain type from the stack. @@ -146,11 +142,7 @@ public: * @param type The type of events to be removed. * @param window The window to remove the events for. */ - virtual void - removeTypeEvents( - GHOST_TEventType type, - GHOST_IWindow* window = 0 - ); + void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow* window = 0); protected: /** @@ -179,4 +171,3 @@ protected: }; #endif // _GHOST_EVENT_MANAGER_H_ - diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 1c00e991520..b14274278ad 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -55,8 +55,7 @@ void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) { - GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); - GHOST_IWindow* window = system->getWindowManager()->getActiveWindow(); + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); unsigned short diff = m_buttons ^ buttons; @@ -70,10 +69,9 @@ void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); data->action = (buttons & mask) ? GHOST_kPress : GHOST_kRelease; -// data->pressed = buttons & mask; data->button = i + 1; -// printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); + // printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); m_system.pushEvent(event); } @@ -87,8 +85,7 @@ bool GHOST_NDOFManager::sendMotionEvent() if (m_atRest) return false; - GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); - GHOST_IWindow* window = system->getWindowManager()->getActiveWindow(); + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); @@ -109,11 +106,10 @@ bool GHOST_NDOFManager::sendMotionEvent() data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds - printf("dt = %d ms\n", (int)(m_motionTime - m_prevMotionTime)); - m_prevMotionTime = m_motionTime; -// printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); +// printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", +// data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 4e0888a87a7..a6b4e104c90 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -37,7 +37,6 @@ #include "GHOST_System.h" #include -#include /* just for printf */ #include "GHOST_DisplayManager.h" #include "GHOST_EventManager.h" @@ -196,18 +195,16 @@ bool GHOST_System::getFullScreen(void) bool GHOST_System::dispatchEvents() { + bool handled = false; + // NDOF Motion event is sent only once per dispatch, so do it now: - m_ndofManager->sendMotionEvent(); + handled |= m_ndofManager->sendMotionEvent(); - bool handled; if (m_eventManager) { if (m_input_fidelity_hint == LO_FI) - handled = m_eventManager->dispatchEvents_lo_fi(); + handled |= m_eventManager->dispatchEvents_lo_fi(); else - handled = m_eventManager->dispatchEvents(); - } - else { - handled = false; + handled |= m_eventManager->dispatchEvents(); } m_timerManager->fireTimers(getMilliSeconds()); @@ -276,8 +273,6 @@ GHOST_TSuccess GHOST_System::init() m_timerManager = new GHOST_TimerManager (); m_windowManager = new GHOST_WindowManager (); m_eventManager = new GHOST_EventManager (); -// m_ndofManager = new GHOST_NDOFManager(); -// Each platform now has their own NDOFManager subclass #ifdef GHOST_DEBUG if (m_eventManager) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index c1c6f874222..bb9b3ec450e 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -38,7 +38,7 @@ #include // for debug [mce] -#define _WIN32_IE 0x501 /* shipped before XP, so doesn't impose additional req'm'ts */ +#define _WIN32_IE 0x501 /* shipped before XP, so doesn't impose additional requirements */ #include @@ -113,7 +113,7 @@ GHOST_SystemWin32::GHOST_SystemWin32() // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); - m_input_fidelity_hint = HI_FI; // just for testing... + m_input_fidelity_hint = LO_FI; // just for testing... // register for RawInput devices RAWINPUTDEVICE devices[1]; @@ -180,10 +180,8 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); if (window) { if (window->getValid()) { - // Store the pointer to the window -// if (state != GHOST_kWindowStateFullScreen) { - m_windowManager->addWindow(window); -// } + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); } else { // An invalid window could be one that was used to test for AA @@ -595,7 +593,15 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool k GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) { - return new GHOST_Event(getSystem()->getMilliSeconds(), type, window); + GHOST_System* system = (GHOST_System*)getSystem(); + + if (type == GHOST_kEventWindowActivate) + { + puts("activating window"); + system->getWindowManager()->setActiveWindow(window); + } + + return new GHOST_Event(system->getMilliSeconds(), type, window); } GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, @@ -645,13 +651,12 @@ vendor ID No other registered devices use the c62_ space, so a simple mask will work! */ - // The NDOF manager sends button changes immediately, and *pretends* to // send motion. Mark as 'sent' so motion will always get dispatched. eventSent = true; // multiple events per RAWHID? MSDN hints at this. - printf("%d events\n", (int)raw.data.hid.dwCount); + // printf("%d events\n", (int)raw.data.hid.dwCount); BYTE const* data = &raw.data.hid.bRawData; // MinGW's definition (below) doesn't agree with MSDN reference for bRawData: @@ -688,6 +693,7 @@ No other registered devices use the c62_ space, so a simple mask will work! { unsigned short buttons; memcpy(&buttons, data + 1, sizeof(buttons)); +#if 0 printf("buttons:"); if (buttons) { @@ -699,6 +705,7 @@ No other registered devices use the c62_ space, so a simple mask will work! } else printf(" none\n"); +#endif m_ndofManager->updateButtons(buttons, getMilliSeconds()); break; } @@ -999,8 +1006,20 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_INPUT: { - puts("WM_INPUT"); + // Raw mouse input benefitted from the buffered method, + // but SpaceNav gets along fine (better, even) grabbing single events. + RAWINPUT raw; + RAWINPUT* raw_ptr = &raw; + UINT rawSize = sizeof(RAWINPUT); + + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); + eventSent |= processRawInput(raw, window); + + // necessary? + // DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); + +#if 0 #define RAWCOUNT 10 // just a guess that we'll receive up to 10 event reports // the following code fetches all available, 10 at a time @@ -1028,20 +1047,20 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM RAWINPUT const& raw = rawBuffer[i]; eventSent |= processRawInput(raw, window); } - + // clear processed events from the queue DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); } } +#endif break; } case WM_MOUSEWHEEL: - puts("WM_MOUSEWHEEL"); /* The WM_MOUSEWHEEL message is sent to the focus window * when the mouse wheel is rotated. The DefWindowProc * function propagates the message to the window's parent. * There should be no internal forwarding of the message, - * since DefWindowProc propagates it up the parent chain + * since DefWindowProc propagates it up the parent chain * until it finds a window that processes it. */ event = processWheelEvent(window, wParam, lParam); @@ -1102,7 +1121,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_PAINT: /* An application sends the WM_PAINT message when the system or another application * makes a request to paint a portion of an application's window. The message is sent - * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage * function when the application obtains a WM_PAINT message by using the GetMessage or * PeekMessage function. */ diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index 1ac357ac97f..aa932663e16 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -212,4 +212,4 @@ bool GHOST_WindowManager::getAnyModifiedState() } return isAnyModified; -} \ No newline at end of file +} -- cgit v1.2.3 From 1c2d36344ca1dbeb8e1517c3e58590728109eccc Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 10 Aug 2010 09:56:39 +0000 Subject: Linux compiles again, no SpaceNav yet. --- intern/ghost/intern/GHOST_SystemX11.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index e658df3ce95..dc519039af6 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -75,7 +75,7 @@ typedef struct NDOFPlatformInfo { Display *display; Window window; -// volatile GHOST_TEventNDOFData *currValues; + volatile GHOST_TEventNDOFMotionData *currValues; Atom cmdAtom; Atom motionAtom; Atom btnPressAtom; @@ -173,7 +173,7 @@ init( if (success) { - m_ndofManager = new GHOST_NDOFManagerX11; + m_ndofManager = new GHOST_NDOFManagerX11(*this); m_displayManager = new GHOST_DisplayManagerX11(this); @@ -656,8 +656,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) // [mce] look into this soon, as in find out why some values // are shifted and where this message originates. - m_ndofManager->updateTranslation(t, getMilliseconds); - m_ndofManager->updateRotation(r, getMilliseconds); + m_ndofManager->updateTranslation(t, getMilliSeconds()); + m_ndofManager->updateRotation(r, getMilliSeconds()); // g_event = new GHOST_EventNDOF(getMilliSeconds(), // GHOST_kEventNDOFMotion, @@ -670,7 +670,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) // data.buttons = xcme.data.s[2]; unsigned short buttons = xcme.data.s[2]; - m_ndofManager->updateButtons(buttons, getMilliseconds()); + m_ndofManager->updateButtons(buttons, getMilliSeconds()); // g_event = new GHOST_EventNDOF(getMilliSeconds(), // GHOST_kEventNDOFButton, -- cgit v1.2.3 From 485d1ef06ebd3d25945b14f7987ce84016b5d311 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 12 Aug 2010 04:03:40 +0000 Subject: Updated Win32 tablet code. --- intern/ghost/intern/GHOST_System.cpp | 30 +-- intern/ghost/intern/GHOST_SystemWin32.cpp | 104 ++++---- intern/ghost/intern/GHOST_SystemWin32.h | 7 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 300 +++++++++++++++++++++++ intern/ghost/intern/GHOST_TabletManagerWin32.h | 82 +++++++ intern/ghost/intern/GHOST_WindowCocoa.mm | 2 - intern/ghost/intern/GHOST_WindowWin32.cpp | 53 ++-- intern/ghost/intern/GHOST_WindowWin32.h | 57 +++-- intern/ghost/intern/Utils.c | 182 -------------- intern/ghost/intern/Utils.h | 94 ------- 10 files changed, 518 insertions(+), 393 deletions(-) create mode 100644 intern/ghost/intern/GHOST_TabletManagerWin32.cpp create mode 100644 intern/ghost/intern/GHOST_TabletManagerWin32.h delete mode 100644 intern/ghost/intern/Utils.c delete mode 100644 intern/ghost/intern/Utils.h (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index a6b4e104c90..ea12421b53c 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -291,29 +291,15 @@ GHOST_TSuccess GHOST_System::init() GHOST_TSuccess GHOST_System::exit() { - if (getFullScreen()) { + if (getFullScreen()) endFullScreen(); - } - if (m_displayManager) { - delete m_displayManager; - m_displayManager = 0; - } - if (m_windowManager) { - delete m_windowManager; - m_windowManager = 0; - } - if (m_timerManager) { - delete m_timerManager; - m_timerManager = 0; - } - if (m_eventManager) { - delete m_eventManager; - m_eventManager = 0; - } - if (m_ndofManager) { - delete m_ndofManager; - m_ndofManager = 0; - } + + delete m_displayManager; + delete m_windowManager; + delete m_timerManager; + delete m_eventManager; + delete m_ndofManager; + return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index bb9b3ec450e..9797b5c2924 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -44,10 +44,10 @@ // win64 doesn't define GWL_USERDATA #ifdef WIN32 -#ifndef GWL_USERDATA -#define GWL_USERDATA GWLP_USERDATA -#define GWL_WNDPROC GWLP_WNDPROC -#endif + #ifndef GWL_USERDATA + #define GWL_USERDATA GWLP_USERDATA + #define GWL_WNDPROC GWLP_WNDPROC + #endif #endif #include "GHOST_Debug.h" @@ -61,44 +61,45 @@ #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" #include "GHOST_NDOFManagerWin32.h" +#include "GHOST_TabletManagerWin32.h" // Key code values not found in winuser.h #ifndef VK_MINUS -#define VK_MINUS 0xBD -#endif // VK_MINUS + #define VK_MINUS 0xBD +#endif #ifndef VK_SEMICOLON -#define VK_SEMICOLON 0xBA -#endif // VK_SEMICOLON + #define VK_SEMICOLON 0xBA +#endif #ifndef VK_PERIOD -#define VK_PERIOD 0xBE -#endif // VK_PERIOD + #define VK_PERIOD 0xBE +#endif #ifndef VK_COMMA -#define VK_COMMA 0xBC -#endif // VK_COMMA + #define VK_COMMA 0xBC +#endif #ifndef VK_QUOTE -#define VK_QUOTE 0xDE -#endif // VK_QUOTE + #define VK_QUOTE 0xDE +#endif #ifndef VK_BACK_QUOTE -#define VK_BACK_QUOTE 0xC0 -#endif // VK_BACK_QUOTE + #define VK_BACK_QUOTE 0xC0 +#endif #ifndef VK_SLASH -#define VK_SLASH 0xBF -#endif // VK_SLASH + #define VK_SLASH 0xBF +#endif #ifndef VK_BACK_SLASH -#define VK_BACK_SLASH 0xDC -#endif // VK_BACK_SLASH + #define VK_BACK_SLASH 0xDC +#endif #ifndef VK_EQUALS -#define VK_EQUALS 0xBB -#endif // VK_EQUALS + #define VK_EQUALS 0xBB +#endif #ifndef VK_OPEN_BRACKET -#define VK_OPEN_BRACKET 0xDB -#endif // VK_OPEN_BRACKET + #define VK_OPEN_BRACKET 0xDB +#endif #ifndef VK_CLOSE_BRACKET -#define VK_CLOSE_BRACKET 0xDD -#endif // VK_CLOSE_BRACKET + #define VK_CLOSE_BRACKET 0xDD +#endif #ifndef VK_GR_LESS -#define VK_GR_LESS 0xE2 -#endif // VK_GR_LESS + #define VK_GR_LESS 0xE2 +#endif GHOST_SystemWin32::GHOST_SystemWin32() @@ -106,14 +107,14 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_separateLeftRight(false), m_separateLeftRightInitialized(false) { - m_displayManager = new GHOST_DisplayManagerWin32 (); + m_displayManager = new GHOST_DisplayManagerWin32; GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); m_displayManager->initialize(); // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); - m_input_fidelity_hint = LO_FI; // just for testing... + m_input_fidelity_hint = HI_FI; // just for testing... // register for RawInput devices RAWINPUTDEVICE devices[1]; @@ -132,6 +133,8 @@ GHOST_SystemWin32::~GHOST_SystemWin32() { // Shutdown COM OleUninitialize(); + + delete m_tabletManager; } @@ -176,16 +179,19 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) { - GHOST_Window* window = 0; - window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); + GHOST_WindowWin32* window = + new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); + if (window) { if (window->getValid()) { m_windowManager->addWindow(window); m_windowManager->setActiveWindow(window); + if (m_tabletManager->available()) + window->becomeTabletAware(m_tabletManager); } else { // An invalid window could be one that was used to test for AA - GHOST_Window *other_window = ((GHOST_WindowWin32*)window)->getNextWindow(); + GHOST_WindowWin32* other_window = (GHOST_WindowWin32*) window->getNextWindow(); delete window; window = 0; @@ -329,6 +335,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess success = GHOST_System::init(); m_ndofManager = new GHOST_NDOFManagerWin32(*this); + m_tabletManager = new GHOST_TabletManagerWin32; /* Disable scaling on high DPI displays on Vista */ HMODULE user32 = ::LoadLibraryA("user32.dll"); @@ -374,14 +381,6 @@ GHOST_TSuccess GHOST_SystemWin32::init() return success; } - -GHOST_TSuccess GHOST_SystemWin32::exit() -{ - // [mce] since this duplicates its super, why bother? - return GHOST_System::exit(); -} - - GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const { GHOST_TKey key; @@ -497,9 +496,17 @@ void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window) ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); } +bool eventIsFromTablet() + { + // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs + return GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + } GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) { + if (eventIsFromTablet()) + return NULL; + return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); } @@ -924,11 +931,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM //////////////////////////////////////////////////////////////////////// case WT_PACKET: puts("WT_PACKET"); - window->processWin32TabletEvent(wParam, lParam); + // window->processWin32TabletEvent(wParam, lParam); + m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: case WT_PROXIMITY: - window->processWin32TabletInitEvent(); + // window->processWin32TabletInitEvent(); + m_tabletManager->changeTool(window); break; //////////////////////////////////////////////////////////////////////// @@ -977,11 +986,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_MOUSEMOVE: { - // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs - int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen - if (tabletTool) - puts("(from tablet)"); - else + if (!eventIsFromTablet()) { int xPrev = mousePosX; int yPrev = mousePosY; @@ -992,7 +997,8 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM if (m_input_fidelity_hint == HI_FI) { - /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // int n = + getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); // printf("%d more mouse points found\n", n); } diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 03bf6f08df8..877b3306572 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -57,6 +57,7 @@ class GHOST_EventWindow; class GHOST_EventDragnDrop; class GHOST_WindowWin32; +class GHOST_TabletManagerWin32; /** * WIN32 Implementation of GHOST_System class. @@ -236,7 +237,7 @@ protected: * Closes the system down. * @return A success value. */ - virtual GHOST_TSuccess exit(); +// virtual GHOST_TSuccess exit(); /** * Converts raw WIN32 key codes from the wndproc to GHOST keys. @@ -356,7 +357,8 @@ protected: bool m_separateLeftRight; /** Stores the initialization state of the member m_leftRightDistinguishable. */ bool m_separateLeftRightInitialized; - + + GHOST_TabletManagerWin32* m_tabletManager; }; inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const @@ -370,4 +372,3 @@ inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys) } #endif // _GHOST_SYSTEM_WIN32_H_ - diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp new file mode 100644 index 00000000000..c82ef574b4a --- /dev/null +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -0,0 +1,300 @@ +#include "GHOST_TabletManagerWin32.h" +#include "GHOST_WindowWin32.h" +#include +#include + +#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE +#define PACKETTILT PKEXT_ABSOLUTE +#define PACKETMODE PK_BUTTONS + +#include "pktdef.h" + +#define MAX_QUEUE_SIZE 128 + +GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() + { + resetActiveTool(); + + // open WinTab + lib_Wintab = LoadLibrary("wintab32.dll"); + + if (lib_Wintab) + { + // connect function pointers + func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA"); + func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose"); + func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); + func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); + func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); + + WORD specV, implV; + func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); + func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); + printf("Wintab version %d.%d (%d.%d)\n", + HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); + + // query for overall capabilities and ranges + char tabletName[LC_NAMELEN]; + if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) + puts(tabletName); + + AXIS xRange, yRange; + func_Info(WTI_DEVICES, DVC_X, &xRange); + func_Info(WTI_DEVICES, DVC_Y, &yRange); + + printf("active area: %dx%d\n", xRange.axMax, yRange.axMax); + + AXIS pressureRange; + hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange) && pressureRange.axMax != 0; + + printf("pressure sensitivity: "); + if (hasPressure) + { + printf("%d to %d\n", pressureRange.axMin, pressureRange.axMax); + pressureScale = 1.f / pressureRange.axMax; + } + else + { + printf("none\n"); + pressureScale = 0.f; + } + + AXIS tiltRange; + hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange) && tiltRange.axMax != 0; + + printf("tilt sensitivity: "); + if (hasTilt) + { + printf("%d to %d\n", tiltRange.axMin, tiltRange.axMax); + tiltScale = 1.f / tiltRange.axMax; + } + else + { + printf("none\n"); + tiltScale = 0.f; + } + } + } + +GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32() + { + // close WinTab + FreeLibrary(lib_Wintab); + } + +bool GHOST_TabletManagerWin32::available() + { + return lib_Wintab // driver installed + && func_Info(0,0,NULL); // tablet plugged in + } + +void GHOST_TabletManagerWin32::resetActiveTool() + { + activeTool.type = TABLET_NONE; + activeTool.hasPressure = false; + activeTool.hasTilt = false; + } + +HCTX GHOST_TabletManagerWin32::contextForWindow(GHOST_WindowWin32* window) + { + std::map::iterator i = contexts.find(window); + if (i == contexts.end()) + return 0; // not found + else + return i->second; + } + +void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) + { + if (contextForWindow(window) != 0) + // this window already has a tablet context + return; + + // set up context + LOGCONTEXT archetype; + func_Info(WTI_DEFCONTEXT, 0, &archetype); + + strcpy(archetype.lcName, "merwin special"); + archetype.lcPktData = PACKETDATA; + archetype.lcPktMode = PACKETMODE; + archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES; + +// BEGIN from Wacom's TILTTEST.c + /* output the data in screen coords */ + archetype.lcOutOrgX = archetype.lcOutOrgY = 0; + archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); + /* move origin to upper left */ + archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); +// END + + // open the context + HCTX context = func_Open(window->getHWND(), &archetype, TRUE); + + // request a deep packet queue + int tabletQueueSize = MAX_QUEUE_SIZE; + while (!func_QueueSizeSet(context, tabletQueueSize)) + --tabletQueueSize; + printf("tablet queue size: %d\n", tabletQueueSize); + + contexts[window] = context; + } + +void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) + { + HCTX context = contextForWindow(window); + + if (context) + { + func_Close(context); + // also remove it from our books: + contexts.erase(contexts.find(window)); + } + } + +void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) + { + HCTX context = contextForWindow(window); + + if (context) + { + PACKET packets[MAX_QUEUE_SIZE]; + int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); + printf("processing %d packets from ", n); + + // every packet from a WT_PACKET message comes from the same tool + switch (packets[0].pkCursor) { + case 0: /* first device */ + case 3: /* second device */ + activeTool.type = TABLET_MOUSE; + puts("mouse"); + break; + case 1: + case 4: + activeTool.type = TABLET_PEN; + puts("pen"); + break; + case 2: + case 5: + activeTool.type = TABLET_ERASER; + puts("eraser"); + break; + } + + for (int i = 0; i < n; ++i) + { + PACKET const& packet = packets[i]; + TabletToolData data = {activeTool}; + int x = packet.pkX; + int y = packet.pkY; + + if (data.tool.hasPressure) + { + if (packet.pkNormalPressure) + data.pressure = pressureScale * packet.pkNormalPressure; + else + data.tool.hasPressure = false; + } + + if (data.tool.hasTilt) + { + data.tilt_x = tiltScale * packet.pkTilt.tiltX; + data.tilt_y = tiltScale * packet.pkTilt.tiltY; + } + + printf(" %.3f @ (%d,%d) /%.2f,%.2f/\n", data.pressure, x, y, data.tilt_x, data.tilt_y); + } + } + } + +void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window) + { + HCTX context = contextForWindow(window); + + if (context) + { + puts("-- changing tool --"); + + if (hasPressure) + { + puts(" - pressure"); + activeTool.hasPressure = true; // not necessarily, but good enough for testing + } + + if (hasTilt) + { + puts(" - tilt"); + activeTool.hasTilt = true; + } + +#if 0 +#define kTransducerDeviceIdBitMask 0x0001 +#define kTransducerAbsXBitMask 0x0002 +#define kTransducerAbsYBitMask 0x0004 +#define kTransducerVendor1BitMask 0x0008 +#define kTransducerVendor2BitMask 0x0010 +#define kTransducerVendor3BitMask 0x0020 +#define kTransducerButtonsBitMask 0x0040 +#define kTransducerTiltXBitMask 0x0080 +#define kTransducerTiltYBitMask 0x0100 +#define kTransducerAbsZBitMask 0x0200 +#define kTransducerPressureBitMask 0x0400 +#define kTransducerTangentialPressureBitMask 0x0800 +#define kTransducerOrientInfoBitMask 0x1000 +#define kTransducerRotationBitMask 0x2000 + + // this is what I really want to know: +// UINT active; +// UINT active2 = func_Info(WTI_CURSORS, CSR_ACTIVE, &active); +// printf("active: %d %d\n", active, active2); + + WTPKT toolData; + func_Info(WTI_CURSORS, CSR_PKTDATA, &toolData); + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; + +// UINT cap; +// UINT cap2 = func_Info(WTI_CURSORS, CSR_CAPABILITIES, &cap); + // capabilities same as Mac tablet code? Let's see... + // int cap = CGEventGetIntegerValueField(event, kCGTabletProximityEventCapabilityMask); + printf("cursor capabilities: %d %d\n", cap, cap2); + + if (cap & kTransducerDeviceIdBitMask) + printf(" - device id\n"); + if (cap & kTransducerAbsXBitMask) + printf(" - abs x\n"); + if (cap & kTransducerAbsYBitMask) + printf(" - abs y\n"); + if (cap & kTransducerAbsZBitMask) + printf(" - abs z\n"); + if (cap & kTransducerVendor1BitMask) + printf(" - vendor 1\n"); + if (cap & kTransducerVendor2BitMask) + printf(" - vendor 2\n"); + if (cap & kTransducerVendor3BitMask) + printf(" - vendor 3\n"); + if (cap & kTransducerButtonsBitMask) + printf(" - buttons\n"); + if (cap & kTransducerTiltXBitMask) + { + printf(" - tilt x\n"); + hasTilt = true; + } + if (cap & kTransducerTiltYBitMask) + { + printf(" - tilt y\n"); + hasTilt = true; + } + if (cap & kTransducerPressureBitMask) + { + printf(" - pressure\n"); + hasPressure = true; + } + if (cap & kTransducerTangentialPressureBitMask) + printf(" - tangential pressure\n"); + if (cap & kTransducerOrientInfoBitMask) + printf(" - orientation\n"); + if (cap & kTransducerRotationBitMask) + printf(" - rotation\n"); +#endif + } + } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h new file mode 100644 index 00000000000..d6b8b1c058a --- /dev/null +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -0,0 +1,82 @@ +// safe & friendly Wintab wrapper +// by Mike Erwin, July 2010 + +#ifndef GHOST_TABLET_MANAGER_WIN32_H +#define GHOST_TABLET_MANAGER_WIN32_H + +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN +#include +#include "wintab.h" +#include + +class GHOST_WindowWin32; + +// BEGIN from Wacom's Utils.h +typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); +typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); +typedef BOOL ( API * WTCLOSE ) ( HCTX ); +typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); +typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); +// END + +typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType; + +typedef struct + { + TabletToolType type : 6; // plenty of room to grow + + // capabilities + bool hasPressure : 1; + bool hasTilt : 1; + + } TabletTool; + + +typedef struct + { + TabletTool tool; + + float pressure; + float tilt_x, tilt_y; + + } TabletToolData; + + +class GHOST_TabletManagerWin32 + { + // the Wintab library + HINSTANCE lib_Wintab; // or HMODULE? + + // WinTab function pointers + WTOPENA func_Open; + WTCLOSE func_Close; + WTINFOA func_Info; + WTQUEUESIZESET func_QueueSizeSet; + WTPACKETSGET func_PacketsGet; + + // tablet attributes + bool hasPressure; + float pressureScale; + bool hasTilt; + float tiltScale; + + // candidates for a base class: + TabletTool activeTool; + void resetActiveTool(); + + // book-keeping + std::map contexts; + HCTX contextForWindow(GHOST_WindowWin32*); + +public: + GHOST_TabletManagerWin32(); + ~GHOST_TabletManagerWin32(); + bool available(); // another base class candidate + void openForWindow(GHOST_WindowWin32* window); + void closeForWindow(GHOST_WindowWin32* window); + void processPackets(GHOST_WindowWin32* window); + void changeTool(GHOST_WindowWin32* window); + }; + +#endif diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 23535ba2f59..c7ec3b398c8 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -854,8 +854,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) return GHOST_Window::setModifiedState(isUnsavedChanges); } - - GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index bf250938af1..361223a2cc8 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -38,9 +38,7 @@ #include "GHOST_WindowWin32.h" #include "GHOST_SystemWin32.h" #include "GHOST_DropTargetWin32.h" - -//#include "wintab.h" // for tablets, naturally -#include "Utils.c" // that's right, .c, with permission from Wacom +#include "GHOST_TabletManagerWin32.h" #include // for debug, remove soon [mce] // Need glew for some defines @@ -50,19 +48,19 @@ // MSVC6 still doesn't define M_PI #ifndef M_PI -#define M_PI 3.1415926536 + #define M_PI 3.1415926536 #endif // Some more multisample defines #define WGL_SAMPLE_BUFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 +#define WGL_SAMPLES_ARB 0x2042 // win64 doesn't define GWL_USERDATA #ifdef WIN32 -#ifndef GWL_USERDATA -#define GWL_USERDATA GWLP_USERDATA -#define GWL_WNDPROC GWLP_WNDPROC -#endif + #ifndef GWL_USERDATA + #define GWL_USERDATA GWLP_USERDATA + #define GWL_WNDPROC GWLP_WNDPROC + #endif #endif LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; @@ -121,15 +119,16 @@ GHOST_WindowWin32::GHOST_WindowWin32( GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual,numOfAASamples), m_system(system), + m_tabletManager(NULL), m_hDC(0), m_hGlRc(0), m_hasMouseCaptured(false), m_nPressedButtons(0), m_customCursor(0), - m_wintab(false), - m_tabletData(NULL), - m_tablet(0), - m_maxPressure(0), +// m_wintab(false), +// m_tabletData(NULL), +// m_tablet(0), +// m_maxPressure(0), m_multisample(numOfAASamples), m_multisampleEnabled(msEnabled), m_msPixelFormat(msPixelFormat), @@ -175,10 +174,8 @@ GHOST_WindowWin32::GHOST_WindowWin32( s_windowClassName, // pointer to registered class name title, // pointer to window name WS_OVERLAPPEDWINDOW, // window style - left, // horizontal position of window - top, // vertical position of window - width, // window width - height, // window height + left, top, // window position + width, height, // window size 0, // handle to parent or owner window 0, // handle to menu or child-window identifier ::GetModuleHandle(0), // handle to application instance @@ -189,10 +186,8 @@ GHOST_WindowWin32::GHOST_WindowWin32( s_windowClassName, // pointer to registered class name title, // pointer to window name WS_POPUP | WS_MAXIMIZE, // window style - left, // horizontal position of window - top, // vertical position of window - width, // window width - height, // window height + left, top, // window position + width, height, // window size 0, // handle to parent or owner window 0, // handle to menu or child-window identifier ::GetModuleHandle(0), // handle to application instance @@ -242,6 +237,7 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } +#if 0 m_wintab = LoadWintab(); if (m_wintab) { // let's see if we can initialize tablet here @@ -300,11 +296,13 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } } +#endif } GHOST_WindowWin32::~GHOST_WindowWin32() { +#if 0 if (m_wintab) { if (m_tablet) gpWTClose(m_tablet); @@ -313,6 +311,11 @@ GHOST_WindowWin32::~GHOST_WindowWin32() m_tabletData = NULL; UnloadWintab(); } +#endif + + if (m_tabletManager) + m_tabletManager->closeForWindow(this); + if (m_customCursor) { DestroyCursor(m_customCursor); m_customCursor = NULL; @@ -913,6 +916,13 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur return GHOST_kSuccess; } +void GHOST_WindowWin32::becomeTabletAware(GHOST_TabletManagerWin32* manager) +{ + m_tabletManager = manager; + m_tabletManager->openForWindow(this); +} + +#if 0 void GHOST_WindowWin32::processWin32TabletInitEvent() { if (m_wintab) { @@ -1016,6 +1026,7 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) putchar('\n'); } } +#endif /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index da3c47c39ac..6cb68d2ff52 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -34,8 +34,8 @@ #define _GHOST_WINDOW_WIN32_H_ #ifndef WIN32 -#error WIN32 only! -#endif // WIN32 + #error WIN32 only! +#endif #include "GHOST_Window.h" @@ -43,13 +43,16 @@ #define WIN32_LEAN_AND_MEAN #include +/* #include #define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) #define PACKETMODE PK_BUTTONS #include +*/ class GHOST_SystemWin32; class GHOST_DropTargetWin32; +class GHOST_TabletManagerWin32; /* // typedefs for WinTab functions to allow dynamic loading @@ -105,7 +108,6 @@ public: * Returns the window to replace this one if it's getting replaced * @return The window replacing this one. */ - GHOST_Window *getNextWindow(); /** @@ -249,10 +251,12 @@ public: void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; const GHOST_TabletData* GetTabletData() - { return m_tabletData; } + { return NULL; /*m_tabletData;*/ } - void processWin32TabletInitEvent(); - void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); +// void processWin32TabletInitEvent(); +// void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); + + void becomeTabletAware(GHOST_TabletManagerWin32*); protected: GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd); @@ -293,37 +297,50 @@ protected: * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); + virtual GHOST_TSuccess setWindowCustomCursorShape( + GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, int hotY + ); virtual GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, - int sizey, - int hotX, - int hotY, - int fg_color, - int bg_color - ); - + int sizex, int sizey, + int hotX, int hotY, + int fg_color, int bg_color + ); + /** Pointer to system */ GHOST_SystemWin32 * m_system; + /** Pointer to COM IDropTarget implementor */ GHOST_DropTargetWin32 * m_dropTarget; + + /** Graphics tablet manager. System owns this, Window needs access to it. */ + GHOST_TabletManagerWin32* m_tabletManager; + /** Window handle. */ HWND m_hWnd; + /** Device context handle. */ HDC m_hDC; + /** OpenGL rendering context. */ HGLRC m_hGlRc; + /** The first created OpenGL context (for sharing display lists) */ static HGLRC s_firsthGLRc; + /** The first created device context handle. */ static HDC s_firstHDC; + /** Flag for if window has captured the mouse */ bool m_hasMouseCaptured; + /** Count of number of pressed buttons */ int m_nPressedButtons; + /** HCURSOR structure of the custom cursor */ HCURSOR m_customCursor; @@ -332,15 +349,15 @@ protected: /** WinTab dll handle */ // HMODULE m_wintab; - bool m_wintab; +// bool m_wintab; /** Tablet data for GHOST */ - GHOST_TabletData* m_tabletData; +// GHOST_TabletData* m_tabletData; /** Stores the Tablet context if detected Tablet features using WinTab.dll */ - HCTX m_tablet; - LONG m_maxPressure; - LONG m_maxAzimuth, m_maxAltitude; +// HCTX m_tablet; +// LONG m_maxPressure; +// LONG m_maxAzimuth, m_maxAltitude; /** Preferred number of samples */ GHOST_TUns16 m_multisample; diff --git a/intern/ghost/intern/Utils.c b/intern/ghost/intern/Utils.c deleted file mode 100644 index d354750f7f6..00000000000 --- a/intern/ghost/intern/Utils.c +++ /dev/null @@ -1,182 +0,0 @@ -/*---------------------------------------------------------------------------- - - NAME - Utils.c - - PURPOSE - Some general-purpose functions for the WinTab demos. - - COPYRIGHT - Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved - All rights reserved. - ----------------------------------------------------------------------------- */ - -#include "Utils.h" - -#ifdef WACOM_DEBUG - -void WacomTrace( char *lpszFormat, ...); - -#define WACOM_ASSERT( x ) assert( x ) -#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) -#else -#define WACOM_TRACE(...) -#define WACOM_ASSERT( x ) - -#endif // WACOM_DEBUG - -////////////////////////////////////////////////////////////////////////////// -HINSTANCE ghWintab = NULL; - -WTINFOA gpWTInfoA = NULL; -WTOPENA gpWTOpenA = NULL; -WTGETA gpWTGetA = NULL; -WTSETA gpWTSetA = NULL; -WTCLOSE gpWTClose = NULL; -WTPACKET gpWTPacket = NULL; -WTENABLE gpWTEnable = NULL; -WTOVERLAP gpWTOverlap = NULL; -WTSAVE gpWTSave = NULL; -WTCONFIG gpWTConfig = NULL; -WTRESTORE gpWTRestore = NULL; -WTEXTSET gpWTExtSet = NULL; -WTEXTGET gpWTExtGet = NULL; -WTQUEUESIZESET gpWTQueueSizeSet = NULL; -WTDATAPEEK gpWTDataPeek = NULL; -WTPACKETSGET gpWTPacketsGet = NULL; - -// TODO - add more wintab32 function pointers as needed - -char* gpszProgramName = NULL; - -#define GETPROCADDRESS(type, func) \ - gp##func = (type)GetProcAddress(ghWintab, #func); \ - if (!gp##func){ WACOM_ASSERT(FALSE); UnloadWintab(); return FALSE; } - -////////////////////////////////////////////////////////////////////////////// -// Purpose -// Find wintab32.dll and load it. -// Find the exported functions we need from it. -// -// Returns -// TRUE on success. -// FALSE on failure. -// -BOOL LoadWintab( void ) -{ - ghWintab = LoadLibraryA( "Wintab32.dll" ); - if ( !ghWintab ) - { - DWORD err = GetLastError(); - WACOM_TRACE("LoadLibrary error: %i\n", err); - ShowError("Could not load Wintab32.dll"); - return FALSE; - } - - // Explicitly find the exported Wintab functions in which we are interested. - // We are using the ASCII, not unicode versions (where applicable). - GETPROCADDRESS( WTOPENA, WTOpenA ); - GETPROCADDRESS( WTINFOA, WTInfoA ); - GETPROCADDRESS( WTGETA, WTGetA ); - GETPROCADDRESS( WTSETA, WTSetA ); - GETPROCADDRESS( WTPACKET, WTPacket ); - GETPROCADDRESS( WTCLOSE, WTClose ); - GETPROCADDRESS( WTENABLE, WTEnable ); - GETPROCADDRESS( WTOVERLAP, WTOverlap ); - GETPROCADDRESS( WTSAVE, WTSave ); - GETPROCADDRESS( WTCONFIG, WTConfig ); - GETPROCADDRESS( WTRESTORE, WTRestore ); - GETPROCADDRESS( WTEXTSET, WTExtSet ); - GETPROCADDRESS( WTEXTGET, WTExtGet ); - GETPROCADDRESS( WTQUEUESIZESET, WTQueueSizeSet ); - GETPROCADDRESS( WTDATAPEEK, WTDataPeek ); - GETPROCADDRESS( WTPACKETSGET, WTPacketsGet ); - - - // TODO - don't forget to NULL out pointers in UnloadWintab(). - return TRUE; -} - - - -////////////////////////////////////////////////////////////////////////////// -// Purpose -// Uninitializes use of wintab32.dll -// -// Returns -// Nothing. -// -void UnloadWintab( void ) -{ - WACOM_TRACE( "UnloadWintab()\n" ); - - if ( ghWintab ) - { - FreeLibrary( ghWintab ); - ghWintab = NULL; - } - - gpWTOpenA = NULL; - gpWTClose = NULL; - gpWTInfoA = NULL; - gpWTPacket = NULL; - gpWTEnable = NULL; - gpWTOverlap = NULL; - gpWTSave = NULL; - gpWTConfig = NULL; - gpWTGetA = NULL; - gpWTSetA = NULL; - gpWTRestore = NULL; - gpWTExtSet = NULL; - gpWTExtGet = NULL; - gpWTQueueSizeSet = NULL; - gpWTDataPeek = NULL; - gpWTPacketsGet = NULL; -} - - - -////////////////////////////////////////////////////////////////////////////// -// Purpose -// Display error to user. -// -void ShowError( char *pszErrorMessage ) -{ - WACOM_TRACE( "ShowError()\n" ); - - WACOM_ASSERT( pszErrorMessage ); - - MessageBoxA( NULL, pszErrorMessage, gpszProgramName, MB_OK | MB_ICONHAND ); -} - - - -#ifdef WACOM_DEBUG - -////////////////////////////////////////////////////////////////////////////// - -void WacomTrace( char *lpszFormat, ...) -{ - char szTraceMessage[ 128 ]; - - int nBytesWritten; - - va_list args; - - WACOM_ASSERT( lpszFormat ); - - va_start( args, lpszFormat ); - - nBytesWritten = _vsnprintf( szTraceMessage, sizeof( szTraceMessage ) - 1, - lpszFormat, args ); - - if ( nBytesWritten > 0 ) - { - OutputDebugStringA( szTraceMessage ); - } - - va_end( args ); -} - -#endif // WACOM_DEBUG diff --git a/intern/ghost/intern/Utils.h b/intern/ghost/intern/Utils.h deleted file mode 100644 index e886389796f..00000000000 --- a/intern/ghost/intern/Utils.h +++ /dev/null @@ -1,94 +0,0 @@ -/*---------------------------------------------------------------------------- - - NAME - Utils.h - - PURPOSE - Defines for the general-purpose functions for the WinTab demos. - - COPYRIGHT - Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved - All rights reserved. - ----------------------------------------------------------------------------- */ -#pragma once - -#include -#include -#include -#include - -#include // NOTE: get from wactab header package - - -////////////////////////////////////////////////////////////////////////////// -#define WACOM_DEBUG - -// Ignore warnings about using unsafe string functions. -#pragma warning( disable : 4996 ) - -////////////////////////////////////////////////////////////////////////////// -// Function pointers to Wintab functions exported from wintab32.dll. -typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); -typedef HCTX ( API * WTOPENA )( HWND, LPLOGCONTEXTA, BOOL ); -typedef BOOL ( API * WTGETA ) ( HCTX, LPLOGCONTEXT ); -typedef BOOL ( API * WTSETA ) ( HCTX, LPLOGCONTEXT ); -typedef BOOL ( API * WTCLOSE ) ( HCTX ); -typedef BOOL ( API * WTENABLE ) ( HCTX, BOOL ); -typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); -typedef BOOL ( API * WTOVERLAP ) ( HCTX, BOOL ); -typedef BOOL ( API * WTSAVE ) ( HCTX, LPVOID ); -typedef BOOL ( API * WTCONFIG ) ( HCTX, HWND ); -typedef HCTX ( API * WTRESTORE ) ( HWND, LPVOID, BOOL ); -typedef BOOL ( API * WTEXTSET ) ( HCTX, UINT, LPVOID ); -typedef BOOL ( API * WTEXTGET ) ( HCTX, UINT, LPVOID ); -typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); -typedef int ( API * WTDATAPEEK ) ( HCTX, UINT, UINT, int, LPVOID, LPINT); -typedef int ( API * WTPACKETSGET ) (HCTX, int, LPVOID); - -// TODO - add more wintab32 function defs as needed - -////////////////////////////////////////////////////////////////////////////// -extern char* gpszProgramName; - -// Loaded Wintab32 API functions. -extern HINSTANCE ghWintab; - -extern WTINFOA gpWTInfoA; -extern WTOPENA gpWTOpenA; -extern WTGETA gpWTGetA; -extern WTSETA gpWTSetA; -extern WTCLOSE gpWTClose; -extern WTPACKET gpWTPacket; -extern WTENABLE gpWTEnable; -extern WTOVERLAP gpWTOverlap; -extern WTSAVE gpWTSave; -extern WTCONFIG gpWTConfig; -extern WTRESTORE gpWTRestore; -extern WTEXTSET gpWTExtSet; -extern WTEXTGET gpWTExtGet; -extern WTQUEUESIZESET gpWTQueueSizeSet; -extern WTDATAPEEK gpWTDataPeek; -extern WTPACKETSGET gpWTPacketsGet; - -// TODO - add more wintab32 function pointers as needed - -////////////////////////////////////////////////////////////////////////////// -BOOL LoadWintab( void ); -void UnloadWintab( void ); - -void ShowError( char *pszErrorMessage ); - -////////////////////////////////////////////////////////////////////////////// -#ifdef WACOM_DEBUG - -void WacomTrace( char *lpszFormat, ...); - -#define WACOM_ASSERT( x ) assert( x ) -#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) -#else -#define WACOM_TRACE(...) -#define WACOM_ASSERT( x ) - -#endif // WACOM_DEBUG - -- cgit v1.2.3 From 1232bb69236094f4ac7e5a419b17784b5ea11b83 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 12 Aug 2010 13:04:00 +0000 Subject: Better Intuos4 support on Windows. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 40 ++- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 363 +++++++++++++---------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 37 ++- 3 files changed, 266 insertions(+), 174 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 9797b5c2924..e71a4b9e803 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -140,7 +140,9 @@ GHOST_SystemWin32::~GHOST_SystemWin32() GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const { - // Hardware does not support high resolution timers. We will use GetTickCount instead then. + // If hardware does not support high resolution timers, + // we will use GetTickCount instead. + if (!m_hasPerformanceCounter) { return ::GetTickCount(); } @@ -153,7 +155,7 @@ GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const __int64 delta = 1000*(count-m_start); GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq); - return t; + return t; } @@ -174,7 +176,7 @@ void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns GHOST_IWindow* GHOST_SystemWin32::createWindow( - const STR_String& title, + const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) @@ -195,7 +197,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( delete window; window = 0; - + // If another window is found, let the wm know about that one, but not the old one if (other_window) { @@ -222,7 +224,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) #else GHOST_TUns64 next = timerMgr->nextFireTime(); GHOST_TInt64 maxSleep = next - getMilliSeconds(); - + if (next == GHOST_kFireTimeNever) { ::WaitMessage(); } else if(maxSleep >= 0.0) { @@ -565,7 +567,7 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP { // short fwKeys = LOWORD(wParam); // key flags int zDelta = (short) HIWORD(wParam); // wheel rotation - + // zDelta /= WHEEL_DELTA; // temporary fix below: microsoft now has added more precision, making the above division not work if (zDelta <= 0 ) zDelta= -1; else zDelta= 1; @@ -930,14 +932,22 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - puts("WT_PACKET"); + // puts("WT_PACKET"); // window->processWin32TabletEvent(wParam, lParam); - m_tabletManager->processPackets(window); + m_tabletManager->processPackets((HCTX)lParam); break; case WT_CSRCHANGE: + m_tabletManager->changeTool((HCTX)lParam, wParam); + break; case WT_PROXIMITY: + // description was weird.. give me numbers! + // printf("prox: %d %d\n", LOWORD(lParam), HIWORD(lParam)); + if (LOWORD(lParam) == 0) + { + puts("-- dropping tool --"); + m_tabletManager->dropTool(); + } // window->processWin32TabletInitEvent(); - m_tabletManager->changeTool(window); break; //////////////////////////////////////////////////////////////////////// @@ -997,9 +1007,15 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM if (m_input_fidelity_hint == HI_FI) { - // int n = - getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); - // printf("%d more mouse points found\n", n); + int buttons; + getButtons(buttons); + // don't bother grabbing extra mouse motion unless we're in a stroke + if (buttons) + { + // int n = + getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // printf("%d more mouse points found\n", n); + } } // uncomment here and in getMoreMousePoints to show effectiveness of hi-fi input diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index c82ef574b4a..f152d4586c2 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -2,18 +2,19 @@ #include "GHOST_WindowWin32.h" #include #include +#include -#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE -#define PACKETTILT PKEXT_ABSOLUTE -#define PACKETMODE PK_BUTTONS +#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION +#define PACKETMODE PK_BUTTONS +// #define PACKETTILT PKEXT_ABSOLUTE #include "pktdef.h" -#define MAX_QUEUE_SIZE 128 +#define MAX_QUEUE_SIZE 100 GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() { - resetActiveTool(); + dropTool(); // open WinTab lib_Wintab = LoadLibrary("wintab32.dll"); @@ -26,11 +27,12 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); + func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); WORD specV, implV; func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); - printf("Wintab version %d.%d (%d.%d)\n", + printf("WinTab version %d.%d (%d.%d)\n", HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); // query for overall capabilities and ranges @@ -44,8 +46,11 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() printf("active area: %dx%d\n", xRange.axMax, yRange.axMax); + func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); + func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); + AXIS pressureRange; - hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange) && pressureRange.axMax != 0; + hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);// && pressureRange.axMax != 0; printf("pressure sensitivity: "); if (hasPressure) @@ -59,20 +64,71 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() pressureScale = 0.f; } - AXIS tiltRange; - hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange) && tiltRange.axMax != 0; + printf("tilt sensitivity:\n"); + AXIS tiltRange[3]; + hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, tiltRange); - printf("tilt sensitivity: "); if (hasTilt) { - printf("%d to %d\n", tiltRange.axMin, tiltRange.axMax); - tiltScale = 1.f / tiltRange.axMax; + // cheat by using available data from Intuos4. test on other tablets!!! + azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); + altitudeScale = 1.f / tiltRange[1].axMax; + printf("azi scale %f\n", azimuthScale); + printf("alt scale %f\n", altitudeScale); + + // leave this code in place to help support tablets I haven't tested + const char* axisName[] = {"azimuth","altitude","twist"}; + const char* unitName[] = {NULL,"inch","cm","circle"}; + for (int i = 0; i < 3; ++i) + { + AXIS const& t = tiltRange[i]; + if (t.axResolution) + printf("%s: %d to %d values per %d.%d %s\n", + axisName[i], t.axMin, t.axMax, + HIWORD(t.axResolution), LOWORD(t.axResolution), + unitName[t.axUnits]); + } } else { printf("none\n"); - tiltScale = 0.f; } + +#if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed + // this isn't working for [mce], so let it rest for now + printf("raw tilt sensitivity:\n"); + hasTilt = false; + UINT tag = 0; + UINT extensionCount; + func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); +// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) + for (UINT i = 0; i < extensionCount; ++i) + { + printf("trying extension %d\n", i); + func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); + if (tag == WTX_TILT) + { + hasTilt = true; + break; + } + } + + if (hasTilt) + { + func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); + AXIS tiltRange[2]; + func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange); + printf("%d to %d along x\n", tiltRange[0].axMin, tiltRange[0].axMax); + printf("%d to %d along y\n", tiltRange[1].axMin, tiltRange[1].axMax); + tiltScaleX = 1.f / tiltRange[0].axMax; + tiltScaleY = 1.f / tiltRange[1].axMax; + } + else + { + printf("none\n"); + tiltScaleX = tiltScaleY = 0.f; + } +#endif // WTX_TILT } } @@ -88,13 +144,6 @@ bool GHOST_TabletManagerWin32::available() && func_Info(0,0,NULL); // tablet plugged in } -void GHOST_TabletManagerWin32::resetActiveTool() - { - activeTool.type = TABLET_NONE; - activeTool.hasPressure = false; - activeTool.hasTilt = false; - } - HCTX GHOST_TabletManagerWin32::contextForWindow(GHOST_WindowWin32* window) { std::map::iterator i = contexts.find(window); @@ -112,20 +161,20 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // set up context LOGCONTEXT archetype; - func_Info(WTI_DEFCONTEXT, 0, &archetype); + func_Info(WTI_DEFSYSCTX, 0, &archetype); - strcpy(archetype.lcName, "merwin special"); + strcpy(archetype.lcName, "blender special"); archetype.lcPktData = PACKETDATA; archetype.lcPktMode = PACKETMODE; - archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES; + archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; -// BEGIN from Wacom's TILTTEST.c - /* output the data in screen coords */ - archetype.lcOutOrgX = archetype.lcOutOrgY = 0; - archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); - /* move origin to upper left */ - archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); -// END +/* + if (hasTilt) + { + archetype.lcPktData |= tiltMask; + archetype.lcMoveMask |= tiltMask; + } +*/ // open the context HCTX context = func_Open(window->getHWND(), &archetype, TRUE); @@ -151,150 +200,160 @@ void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) } } -void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) +void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolData& data) { - HCTX context = contextForWindow(window); + // this code used to live in GHOST_WindowWin32 + // now it lives here + + float vecLen; + float altRad, azmRad; /* in radians */ + + /* + from the wintab spec: + orAzimuth Specifies the clockwise rotation of the + cursor about the z axis through a full circular range. + + orAltitude Specifies the angle with the x-y plane + through a signed, semicircular range. Positive values + specify an angle upward toward the positive z axis; + negative values specify an angle downward toward the negative z axis. + + wintab.h defines .orAltitude as a UINT but documents .orAltitude + as positive for upward angles and negative for downward angles. + WACOM uses negative altitude values to show that the pen is inverted; + therefore we cast .orAltitude as an (int) and then use the absolute value. + */ + + /* convert raw fixed point data to radians */ + altRad = fabs(ort.orAltitude) * altitudeScale * M_PI/2.0; + azmRad = ort.orAzimuth * azimuthScale * M_PI*2.0; + + /* find length of the stylus' projected vector on the XY plane */ + vecLen = cos(altRad); + + /* from there calculate X and Y components based on azimuth */ + data.tilt_x = sin(azmRad) * vecLen; + data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; + } - if (context) +void GHOST_TabletManagerWin32::processPackets(HCTX context) + { + PACKET packets[MAX_QUEUE_SIZE]; + int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); +// printf("processing %d packets\n", n); + + for (int i = 0; i < n; ++i) { - PACKET packets[MAX_QUEUE_SIZE]; - int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); - printf("processing %d packets from ", n); + PACKET const& packet = packets[i]; + TabletToolData data = {activeTool}; + int x = packet.pkX; + int y = packet.pkY; + + if (activeTool.type == TABLET_MOUSE) + if (x == prevMouseX && y == prevMouseY) + // don't send any "mouse hasn't moved" events + continue; + else { + prevMouseX = x; + prevMouseY = y; + } // every packet from a WT_PACKET message comes from the same tool - switch (packets[0].pkCursor) { - case 0: /* first device */ - case 3: /* second device */ - activeTool.type = TABLET_MOUSE; - puts("mouse"); + switch (activeTool.type) + { + case TABLET_MOUSE: + printf("mouse"); break; - case 1: - case 4: - activeTool.type = TABLET_PEN; - puts("pen"); + case TABLET_PEN: + printf("pen"); break; - case 2: - case 5: - activeTool.type = TABLET_ERASER; - puts("eraser"); + case TABLET_ERASER: + printf("eraser"); break; - } + default: + printf("???"); + } - for (int i = 0; i < n; ++i) - { - PACKET const& packet = packets[i]; - TabletToolData data = {activeTool}; - int x = packet.pkX; - int y = packet.pkY; + printf(" (%d,%d)", x, y); - if (data.tool.hasPressure) + if (activeTool.hasPressure) + { + if (packet.pkNormalPressure) { - if (packet.pkNormalPressure) - data.pressure = pressureScale * packet.pkNormalPressure; - else - data.tool.hasPressure = false; + data.pressure = pressureScale * packet.pkNormalPressure; + printf(" %d%%", (int)(100 * data.pressure)); } + else + data.tool.hasPressure = false; + } - if (data.tool.hasTilt) - { - data.tilt_x = tiltScale * packet.pkTilt.tiltX; - data.tilt_y = tiltScale * packet.pkTilt.tiltY; - } + if (activeTool.hasTilt) + { + // ORIENTATION const& tilt = packet.pkOrientation; + // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); + convertTilt(packet.pkOrientation, data); - printf(" %.3f @ (%d,%d) /%.2f,%.2f/\n", data.pressure, x, y, data.tilt_x, data.tilt_y); + // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; + // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); } + + putchar('\n'); } } -void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window) +void GHOST_TabletManagerWin32::changeTool(HCTX context, UINT serialNumber) { - HCTX context = contextForWindow(window); + puts("-- changing tool --"); - if (context) - { - puts("-- changing tool --"); + dropTool(); - if (hasPressure) - { - puts(" - pressure"); - activeTool.hasPressure = true; // not necessarily, but good enough for testing - } + PACKET packet; + func_Packet(context, serialNumber, &packet); + UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - if (hasTilt) - { - puts(" - tilt"); - activeTool.hasTilt = true; - } + printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); -#if 0 -#define kTransducerDeviceIdBitMask 0x0001 -#define kTransducerAbsXBitMask 0x0002 -#define kTransducerAbsYBitMask 0x0004 -#define kTransducerVendor1BitMask 0x0008 -#define kTransducerVendor2BitMask 0x0010 -#define kTransducerVendor3BitMask 0x0020 -#define kTransducerButtonsBitMask 0x0040 -#define kTransducerTiltXBitMask 0x0080 -#define kTransducerTiltYBitMask 0x0100 -#define kTransducerAbsZBitMask 0x0200 -#define kTransducerPressureBitMask 0x0400 -#define kTransducerTangentialPressureBitMask 0x0800 -#define kTransducerOrientInfoBitMask 0x1000 -#define kTransducerRotationBitMask 0x2000 - - // this is what I really want to know: -// UINT active; -// UINT active2 = func_Info(WTI_CURSORS, CSR_ACTIVE, &active); -// printf("active: %d %d\n", active, active2); - - WTPKT toolData; - func_Info(WTI_CURSORS, CSR_PKTDATA, &toolData); - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; - -// UINT cap; -// UINT cap2 = func_Info(WTI_CURSORS, CSR_CAPABILITIES, &cap); - // capabilities same as Mac tablet code? Let's see... - // int cap = CGEventGetIntegerValueField(event, kCGTabletProximityEventCapabilityMask); - printf("cursor capabilities: %d %d\n", cap, cap2); - - if (cap & kTransducerDeviceIdBitMask) - printf(" - device id\n"); - if (cap & kTransducerAbsXBitMask) - printf(" - abs x\n"); - if (cap & kTransducerAbsYBitMask) - printf(" - abs y\n"); - if (cap & kTransducerAbsZBitMask) - printf(" - abs z\n"); - if (cap & kTransducerVendor1BitMask) - printf(" - vendor 1\n"); - if (cap & kTransducerVendor2BitMask) - printf(" - vendor 2\n"); - if (cap & kTransducerVendor3BitMask) - printf(" - vendor 3\n"); - if (cap & kTransducerButtonsBitMask) - printf(" - buttons\n"); - if (cap & kTransducerTiltXBitMask) - { - printf(" - tilt x\n"); - hasTilt = true; - } - if (cap & kTransducerTiltYBitMask) - { - printf(" - tilt y\n"); - hasTilt = true; - } - if (cap & kTransducerPressureBitMask) - { - printf(" - pressure\n"); - hasPressure = true; - } - if (cap & kTransducerTangentialPressureBitMask) - printf(" - tangential pressure\n"); - if (cap & kTransducerOrientInfoBitMask) - printf(" - orientation\n"); - if (cap & kTransducerRotationBitMask) - printf(" - rotation\n"); -#endif + switch (cursor) + { + case 0: // older Intuos tablets can track two cursors at once + case 3: // so we test for both here + activeTool.type = TABLET_MOUSE; + break; + case 1: + case 4: + activeTool.type = TABLET_PEN; + break; + case 2: + case 5: + activeTool.type = TABLET_ERASER; + break; + default: + activeTool.type = TABLET_NONE; } + + WTPKT toolData; + func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData); + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; +// activeTool.hasTilt = toolData & tiltMask; + + if (activeTool.hasPressure) + puts(" - pressure"); + + if (activeTool.hasTilt) + puts(" - tilt"); + + // and just for fun: + if (toolData & PK_BUTTONS) + puts(" - buttons"); + } + +void GHOST_TabletManagerWin32::dropTool() + { + activeTool.type = TABLET_NONE; + activeTool.hasPressure = false; + activeTool.hasTilt = false; + + prevMouseX = prevMouseY = 0; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index d6b8b1c058a..1a046974649 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -18,13 +18,14 @@ typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); typedef BOOL ( API * WTCLOSE ) ( HCTX ); typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); +typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); // END typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType; typedef struct { - TabletToolType type : 6; // plenty of room to grow + TabletToolType type : 4; // plenty of room to grow // capabilities bool hasPressure : 1; @@ -46,7 +47,7 @@ typedef struct class GHOST_TabletManagerWin32 { // the Wintab library - HINSTANCE lib_Wintab; // or HMODULE? + HMODULE lib_Wintab; // WinTab function pointers WTOPENA func_Open; @@ -54,29 +55,45 @@ class GHOST_TabletManagerWin32 WTINFOA func_Info; WTQUEUESIZESET func_QueueSizeSet; WTPACKETSGET func_PacketsGet; + WTPACKET func_Packet; // tablet attributes bool hasPressure; float pressureScale; bool hasTilt; - float tiltScale; - - // candidates for a base class: + float azimuthScale; + float altitudeScale; +// float tiltScaleX; +// float tiltScaleY; +// UINT tiltMask; + UINT cursorCount; + UINT cursorBase; + + // candidate for a base class: TabletTool activeTool; - void resetActiveTool(); + + int prevMouseX; + int prevMouseY; // book-keeping std::map contexts; HCTX contextForWindow(GHOST_WindowWin32*); + void convertTilt(ORIENTATION const&, TabletToolData&); + public: GHOST_TabletManagerWin32(); ~GHOST_TabletManagerWin32(); + bool available(); // another base class candidate - void openForWindow(GHOST_WindowWin32* window); - void closeForWindow(GHOST_WindowWin32* window); - void processPackets(GHOST_WindowWin32* window); - void changeTool(GHOST_WindowWin32* window); + + void openForWindow(GHOST_WindowWin32*); + void closeForWindow(GHOST_WindowWin32*); + + void processPackets(HCTX); + + void changeTool(HCTX, UINT serialNumber); + void dropTool(); }; #endif -- cgit v1.2.3 From fc5c4d98f4a52b7e405efed307427ace4a593f7b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 12 Aug 2010 14:02:38 +0000 Subject: Minor cleanup of Windows tablet code. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 5 ----- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 11 +++++++---- intern/ghost/intern/GHOST_TabletManagerWin32.h | 20 +++++++++++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index e71a4b9e803..ee2484ec1dd 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -932,22 +932,17 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - // puts("WT_PACKET"); - // window->processWin32TabletEvent(wParam, lParam); m_tabletManager->processPackets((HCTX)lParam); break; case WT_CSRCHANGE: m_tabletManager->changeTool((HCTX)lParam, wParam); break; case WT_PROXIMITY: - // description was weird.. give me numbers! - // printf("prox: %d %d\n", LOWORD(lParam), HIWORD(lParam)); if (LOWORD(lParam) == 0) { puts("-- dropping tool --"); m_tabletManager->dropTool(); } - // window->processWin32TabletInitEvent(); break; //////////////////////////////////////////////////////////////////////// diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index f152d4586c2..864cf632d06 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -1,3 +1,6 @@ +// safe & friendly WinTab wrapper +// by Mike Erwin, July 2010 + #include "GHOST_TabletManagerWin32.h" #include "GHOST_WindowWin32.h" #include @@ -73,8 +76,6 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() // cheat by using available data from Intuos4. test on other tablets!!! azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); altitudeScale = 1.f / tiltRange[1].axMax; - printf("azi scale %f\n", azimuthScale); - printf("alt scale %f\n", altitudeScale); // leave this code in place to help support tablets I haven't tested const char* axisName[] = {"azimuth","altitude","twist"}; @@ -101,8 +102,8 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() UINT tag = 0; UINT extensionCount; func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); -// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) for (UINT i = 0; i < extensionCount; ++i) +// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) { printf("trying extension %d\n", i); func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); @@ -299,6 +300,8 @@ void GHOST_TabletManagerWin32::processPackets(HCTX context) } putchar('\n'); + + // at this point, construct a GHOST event and push it into the queue! } } @@ -312,7 +315,7 @@ void GHOST_TabletManagerWin32::changeTool(HCTX context, UINT serialNumber) func_Packet(context, serialNumber, &packet); UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); + // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); switch (cursor) { diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 1a046974649..5686684e12a 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -1,4 +1,4 @@ -// safe & friendly Wintab wrapper +// safe & friendly WinTab wrapper // by Mike Erwin, July 2010 #ifndef GHOST_TABLET_MANAGER_WIN32_H @@ -96,4 +96,22 @@ public: void dropTool(); }; +/* +The tablet manager is driven by the following Windows event processing code: + +case WT_PACKET: + m_tabletManager->processPackets((HCTX)lParam); + break; +case WT_CSRCHANGE: + m_tabletManager->changeTool((HCTX)lParam, wParam); + break; +case WT_PROXIMITY: + if (LOWORD(lParam) == 0) + { + puts("-- dropping tool --"); + m_tabletManager->dropTool(); + } + break; +*/ + #endif -- cgit v1.2.3 From 7428380cc366025ae51f6245a5d0a837a7210c8d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 13 Aug 2010 00:34:57 +0000 Subject: still working on tablet for Windows... --- intern/ghost/intern/GHOST_Buttons.cpp | 5 + intern/ghost/intern/GHOST_Buttons.h | 9 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 11 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 194 +++++++++++++++-------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 2 +- 5 files changed, 150 insertions(+), 71 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp index edccb24d5a1..8b46d777dbb 100644 --- a/intern/ghost/intern/GHOST_Buttons.cpp +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -71,4 +71,9 @@ void GHOST_Buttons::clear() m_ButtonRight = false; } +bool GHOST_Buttons::anyDown() const +{ + return m_ButtonLeft || m_ButtonMiddle || m_ButtonRight; +} + GHOST_Buttons::~GHOST_Buttons() {} diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h index 3dd10af0112..b35f68e4400 100644 --- a/intern/ghost/intern/GHOST_Buttons.h +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -67,8 +67,13 @@ struct GHOST_Buttons { /** * Sets the state of all buttons to up. */ - virtual void clear(); - + virtual void clear(); + + /** + * Are any buttons currently pressed? + */ + bool anyDown() const; + GHOST_TUns8 m_ButtonLeft : 1; GHOST_TUns8 m_ButtonMiddle : 1; GHOST_TUns8 m_ButtonRight : 1; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index ee2484ec1dd..b8673ef3963 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -506,8 +506,9 @@ bool eventIsFromTablet() GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) { - if (eventIsFromTablet()) - return NULL; + puts("ghost button event"); +// if (eventIsFromTablet()) +// return NULL; return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); } @@ -932,7 +933,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - m_tabletManager->processPackets((HCTX)lParam); + m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: m_tabletManager->changeTool((HCTX)lParam, wParam); @@ -1002,10 +1003,10 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM if (m_input_fidelity_hint == HI_FI) { - int buttons; + GHOST_Buttons buttons; getButtons(buttons); // don't bother grabbing extra mouse motion unless we're in a stroke - if (buttons) + if (buttons.anyDown()) { // int n = getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 864cf632d06..0b69dcb300d 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -3,6 +3,9 @@ #include "GHOST_TabletManagerWin32.h" #include "GHOST_WindowWin32.h" +#include "GHOST_System.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventButton.h" #include #include #include @@ -162,20 +165,39 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // set up context LOGCONTEXT archetype; - func_Info(WTI_DEFSYSCTX, 0, &archetype); +// func_Info(WTI_DEFSYSCTX, 0, &archetype); + func_Info(WTI_DEFCONTEXT, 0, &archetype); strcpy(archetype.lcName, "blender special"); archetype.lcPktData = PACKETDATA; archetype.lcPktMode = PACKETMODE; - archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; - -/* - if (hasTilt) +// archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; + archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + + // we want first 5 buttons + archetype.lcBtnDnMask = 0x1f; + archetype.lcBtnUpMask = 0x1f; + +// BEGIN derived from Wacom's TILTTEST.C: + AXIS TabletX, TabletY; + func_Info(WTI_DEVICES,DVC_X,&TabletX); + func_Info(WTI_DEVICES,DVC_Y,&TabletY); + archetype.lcInOrgX = 0; + archetype.lcInOrgY = 0; + archetype.lcInExtX = TabletX.axMax; + archetype.lcInExtY = TabletY.axMax; + /* output the data in screen coords */ + archetype.lcOutOrgX = archetype.lcOutOrgY = 0; + archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); + /* move origin to upper left */ + archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); +// END + +/* if (hasTilt) { archetype.lcPktData |= tiltMask; archetype.lcMoveMask |= tiltMask; - } -*/ + } */ // open the context HCTX context = func_Open(window->getHWND(), &archetype, TRUE); @@ -237,71 +259,117 @@ void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolDat data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; } -void GHOST_TabletManagerWin32::processPackets(HCTX context) +void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { - PACKET packets[MAX_QUEUE_SIZE]; - int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); -// printf("processing %d packets\n", n); + HCTX context = contextForWindow(window); - for (int i = 0; i < n; ++i) + if (context) { - PACKET const& packet = packets[i]; - TabletToolData data = {activeTool}; - int x = packet.pkX; - int y = packet.pkY; - - if (activeTool.type == TABLET_MOUSE) - if (x == prevMouseX && y == prevMouseY) - // don't send any "mouse hasn't moved" events - continue; - else { - prevMouseX = x; - prevMouseY = y; - } - - // every packet from a WT_PACKET message comes from the same tool - switch (activeTool.type) - { - case TABLET_MOUSE: - printf("mouse"); - break; - case TABLET_PEN: - printf("pen"); - break; - case TABLET_ERASER: - printf("eraser"); - break; - default: - printf("???"); - } - - printf(" (%d,%d)", x, y); - - if (activeTool.hasPressure) + PACKET packets[MAX_QUEUE_SIZE]; + int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); + // printf("processing %d packets\n", n); + + for (int i = 0; i < n; ++i) { - if (packet.pkNormalPressure) + PACKET const& packet = packets[i]; + TabletToolData data = {activeTool}; + int x = packet.pkX; + int y = packet.pkY; + + if (activeTool.type == TABLET_MOUSE) + if (x == prevMouseX && y == prevMouseY) + // don't send any "mouse hasn't moved" events + continue; + else { + prevMouseX = x; + prevMouseY = y; + } + + // every packet from a WT_PACKET message comes from the same tool + switch (activeTool.type) { - data.pressure = pressureScale * packet.pkNormalPressure; - printf(" %d%%", (int)(100 * data.pressure)); + case TABLET_MOUSE: + printf("mouse"); + break; + case TABLET_PEN: + printf("pen"); + break; + case TABLET_ERASER: + printf("eraser"); + break; + default: + printf("???"); } - else - data.tool.hasPressure = false; - } + + printf(" (%d,%d)", x, y); + + if (activeTool.hasPressure) + { + if (packet.pkNormalPressure) + { + data.pressure = pressureScale * packet.pkNormalPressure; + printf(" %d%%", (int)(100 * data.pressure)); + } + else + data.tool.hasPressure = false; + } + + if (activeTool.hasTilt) + { + // ORIENTATION const& tilt = packet.pkOrientation; + // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); + convertTilt(packet.pkOrientation, data); + + // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; + // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + } + + putchar('\n'); - if (activeTool.hasTilt) - { - // ORIENTATION const& tilt = packet.pkOrientation; - // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); - convertTilt(packet.pkOrientation, data); + // at this point, construct a GHOST event and push it into the queue! + // (having trouble with Wacom mouse scaling, so ignore it for now) - // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; - // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); +// if (activeTool.type == TABLET_PEN || activeTool.type == TABLET_ERASER) + { + GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + + if (packet.pkButtons) + { + // which button? + GHOST_TButtonMask e_button; + int buttonNumber = LOWORD(packet.pkButtons); + e_button = (GHOST_TButtonMask) buttonNumber; + + // pressed or released? + GHOST_TEventType e_action; + int buttonAction = HIWORD(packet.pkButtons); + if (buttonAction == TBN_DOWN) + e_action = GHOST_kEventButtonDown; + else + e_action = GHOST_kEventButtonUp; + + printf("button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); + + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + +// system->pushEvent(e); + } + else + { + GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); + + // use older TabletData struct for testing until mine is in place + GHOST_TabletData& e_data = ((GHOST_TEventCursorData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; + +// system->pushEvent(e); + } + } } - - putchar('\n'); - - // at this point, construct a GHOST event and push it into the queue! } } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 5686684e12a..290798a6bfb 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -90,7 +90,7 @@ public: void openForWindow(GHOST_WindowWin32*); void closeForWindow(GHOST_WindowWin32*); - void processPackets(HCTX); + void processPackets(GHOST_WindowWin32*); void changeTool(HCTX, UINT serialNumber); void dropTool(); -- cgit v1.2.3 From 91e2a5517190b532a78515956391d2e699ae88b8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 14 Aug 2010 21:01:09 +0000 Subject: continued Win32 tablet hackery --- intern/ghost/intern/GHOST_Buttons.cpp | 5 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 39 ++- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 313 ++++++++++++++--------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 21 +- 4 files changed, 239 insertions(+), 139 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp index 8b46d777dbb..5a1f5dea430 100644 --- a/intern/ghost/intern/GHOST_Buttons.cpp +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -35,6 +35,7 @@ GHOST_Buttons::GHOST_Buttons() clear(); } +GHOST_Buttons::~GHOST_Buttons() {} bool GHOST_Buttons::get(GHOST_TButtonMask mask) const { @@ -73,7 +74,5 @@ void GHOST_Buttons::clear() bool GHOST_Buttons::anyDown() const { - return m_ButtonLeft || m_ButtonMiddle || m_ButtonRight; + return m_ButtonLeft || m_ButtonMiddle || m_ButtonRight; } - -GHOST_Buttons::~GHOST_Buttons() {} diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index b8673ef3963..0f567dec4e2 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -247,6 +247,9 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) } } while (waitForEvent && !anyProcessed); + if (m_tabletManager->processPackets()) + anyProcessed = true; + return anyProcessed; } @@ -500,15 +503,28 @@ void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window) bool eventIsFromTablet() { - // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs - return GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + // this (apparently) gives the packet serial number, which only tablet events have + return GetMessageExtraInfo() != 0; +// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs +// static int all_magic = 0; +// int magic = GetMessageExtraInfo(); +// all_magic |= magic; +// printf("from tablet? %08x %08x\n", magic, all_magic); +// return magic & 0x7f; // true for tablet mouse, not just pen } GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) { - puts("ghost button event"); -// if (eventIsFromTablet()) -// return NULL; + if (eventIsFromTablet()) + return NULL; + + static GHOST_Buttons buttons; + if (type == GHOST_kEventButtonUp && !buttons.get(mask)) + // discard rogue button up events (probably from tablet) + return NULL; + buttons.set(mask, type == GHOST_kEventButtonDown); + + printf("system button %d %s\n", mask, (type == GHOST_kEventButtonDown) ? "down" : (type == GHOST_kEventButtonUp) ? "up" : "???"); return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); } @@ -516,6 +532,8 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x_screen, int y_screen) { + printf("system cursor (%d,%d)\n", x_screen, y_screen); + GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; @@ -933,10 +951,11 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: + puts("WT_PACKET"); m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: - m_tabletManager->changeTool((HCTX)lParam, wParam); + m_tabletManager->changeTool(window, wParam); break; case WT_PROXIMITY: if (LOWORD(lParam) == 0) @@ -1034,8 +1053,10 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); eventSent |= processRawInput(raw, window); - // necessary? - // DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); + if (processRawInput(raw, window)) + eventSent = true; +// else +// DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); #if 0 #define RAWCOUNT 10 @@ -1067,7 +1088,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM } // clear processed events from the queue - DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); + // DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); } } #endif diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 0b69dcb300d..9278ad2f48e 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -11,14 +11,28 @@ #include #define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION -#define PACKETMODE PK_BUTTONS +#define PACKETMODE 0 /*PK_BUTTONS*/ // #define PACKETTILT PKEXT_ABSOLUTE #include "pktdef.h" #define MAX_QUEUE_SIZE 100 +static void print(AXIS const& t, char const* label = NULL) + { + const char* unitName[] = {"dinosaur","inch","cm","circle"}; + + if (label) + printf("%s: ", label); + + printf("%d to %d, %d.%d per %s\n", + t.axMin, t.axMax, + HIWORD(t.axResolution), LOWORD(t.axResolution), + unitName[t.axUnits]); + } + GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() + : activeWindow(NULL) { dropTool(); @@ -46,56 +60,45 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) puts(tabletName); + puts("active tablet area"); AXIS xRange, yRange; func_Info(WTI_DEVICES, DVC_X, &xRange); func_Info(WTI_DEVICES, DVC_Y, &yRange); + print(xRange,"x"); print(yRange,"y"); - printf("active area: %dx%d\n", xRange.axMax, yRange.axMax); func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); + puts("pressure sensitivity"); AXIS pressureRange; hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);// && pressureRange.axMax != 0; + print(pressureRange); - printf("pressure sensitivity: "); if (hasPressure) - { - printf("%d to %d\n", pressureRange.axMin, pressureRange.axMax); pressureScale = 1.f / pressureRange.axMax; - } else - { - printf("none\n"); pressureScale = 0.f; - } - printf("tilt sensitivity:\n"); + puts("tilt sensitivity"); AXIS tiltRange[3]; hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, tiltRange); if (hasTilt) { - // cheat by using available data from Intuos4. test on other tablets!!! - azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); - altitudeScale = 1.f / tiltRange[1].axMax; - // leave this code in place to help support tablets I haven't tested const char* axisName[] = {"azimuth","altitude","twist"}; - const char* unitName[] = {NULL,"inch","cm","circle"}; for (int i = 0; i < 3; ++i) - { - AXIS const& t = tiltRange[i]; - if (t.axResolution) - printf("%s: %d to %d values per %d.%d %s\n", - axisName[i], t.axMin, t.axMax, - HIWORD(t.axResolution), LOWORD(t.axResolution), - unitName[t.axUnits]); - } + print(tiltRange[i], axisName[i]); + + // cheat by using available data from Intuos4. test on other tablets!!! + azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); + altitudeScale = 1.f / tiltRange[1].axMax; } else { - printf("none\n"); + puts("none"); + azimuthScale = altitudeScale = 0.f; } #if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed @@ -106,7 +109,6 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() UINT extensionCount; func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); for (UINT i = 0; i < extensionCount; ++i) -// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) { printf("trying extension %d\n", i); func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); @@ -119,17 +121,17 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() if (hasTilt) { - func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); AXIS tiltRange[2]; func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange); - printf("%d to %d along x\n", tiltRange[0].axMin, tiltRange[0].axMax); - printf("%d to %d along y\n", tiltRange[1].axMin, tiltRange[1].axMax); + print("x", tiltRange[0]); + print("y", tiltRange[1]); tiltScaleX = 1.f / tiltRange[0].axMax; tiltScaleY = 1.f / tiltRange[1].axMax; + func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); } else { - printf("none\n"); + puts("none"); tiltScaleX = tiltScaleY = 0.f; } #endif // WTX_TILT @@ -165,18 +167,27 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // set up context LOGCONTEXT archetype; -// func_Info(WTI_DEFSYSCTX, 0, &archetype); - func_Info(WTI_DEFCONTEXT, 0, &archetype); + func_Info(WTI_DEFSYSCTX, 0, &archetype); +// func_Info(WTI_DEFCONTEXT, 0, &archetype); strcpy(archetype.lcName, "blender special"); - archetype.lcPktData = PACKETDATA; - archetype.lcPktMode = PACKETMODE; -// archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; - archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + WTPKT packetData = PACKETDATA; + if (!hasPressure) + packetData &= ~PK_NORMAL_PRESSURE; + if (!hasTilt) + packetData &= ~PK_ORIENTATION; + archetype.lcPktData = packetData; + + archetype.lcPktMode = PACKETMODE; + archetype.lcOptions |= /*CXO_MESSAGES |*/ CXO_CSRMESSAGES; +// archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + +#if PACKETMODE & PK_BUTTONS // we want first 5 buttons archetype.lcBtnDnMask = 0x1f; archetype.lcBtnUpMask = 0x1f; +#endif // BEGIN derived from Wacom's TILTTEST.C: AXIS TabletX, TabletY; @@ -259,16 +270,23 @@ void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolDat data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; } -void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) +bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { + if (window == NULL) + window = activeWindow; + HCTX context = contextForWindow(window); + bool anyProcessed = false; + if (context) { +// PACKET packet; +// func_Packet(context, serialNumber, &packet); PACKET packets[MAX_QUEUE_SIZE]; int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); - // printf("processing %d packets\n", n); - +// printf("processing %d packets\n", n); + for (int i = 0; i < n; ++i) { PACKET const& packet = packets[i]; @@ -277,15 +295,20 @@ void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) int y = packet.pkY; if (activeTool.type == TABLET_MOUSE) - if (x == prevMouseX && y == prevMouseY) + if (x == prevMouseX && y == prevMouseY && packet.pkButtons == prevButtons) // don't send any "mouse hasn't moved" events continue; else { prevMouseX = x; prevMouseY = y; } - - // every packet from a WT_PACKET message comes from the same tool + + anyProcessed = true; + + // Since we're using a digitizing context, we need to + // move the on-screen cursor ourselves. + // SetCursorPos(x, y); + switch (activeTool.type) { case TABLET_MOUSE: @@ -316,108 +339,159 @@ void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) if (activeTool.hasTilt) { - // ORIENTATION const& tilt = packet.pkOrientation; - // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); - convertTilt(packet.pkOrientation, data); - + ORIENTATION const& o = packet.pkOrientation; + + if (o.orAzimuth || o.orAltitude) + { + convertTilt(o, data); + printf(" /%d,%d/", o.orAzimuth, o.orAltitude); + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) + { + // really should fix the initial test for activeTool.hasTilt, + // not apply a band-aid here. + data.tool.hasTilt = false; + data.tilt_x = 0.f; + data.tilt_y = 0.f; + } + } + else + data.tool.hasTilt = false; + // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); } - - putchar('\n'); // at this point, construct a GHOST event and push it into the queue! - // (having trouble with Wacom mouse scaling, so ignore it for now) -// if (activeTool.type == TABLET_PEN || activeTool.type == TABLET_ERASER) - { - GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); - if (packet.pkButtons) - { - // which button? - GHOST_TButtonMask e_button; - int buttonNumber = LOWORD(packet.pkButtons); - e_button = (GHOST_TButtonMask) buttonNumber; - - // pressed or released? - GHOST_TEventType e_action; - int buttonAction = HIWORD(packet.pkButtons); - if (buttonAction == TBN_DOWN) - e_action = GHOST_kEventButtonDown; - else - e_action = GHOST_kEventButtonUp; - - printf("button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); - - GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); - -// system->pushEvent(e); - } + // any buttons changed? + #if PACKETMODE & PK_BUTTONS + // relative buttons mode + if (packet.pkButtons) + { + // which button? + GHOST_TButtonMask e_button; + int buttonNumber = LOWORD(packet.pkButtons); + e_button = (GHOST_TButtonMask) buttonNumber; + + // pressed or released? + GHOST_TEventType e_action; + int buttonAction = HIWORD(packet.pkButtons); + if (buttonAction == TBN_DOWN) + e_action = GHOST_kEventButtonDown; else + e_action = GHOST_kEventButtonUp; + + printf(" button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); + + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + + system->pushEvent(e); + } + #else + // absolute buttons mode + UINT diff = prevButtons ^ packet.pkButtons; + if (diff) + { + for (int i = 0; i < 32 /*GHOST_kButtonNumMasks*/; ++i) { - GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); + UINT mask = 1 << i; + + if (diff & mask) + { + GHOST_TButtonMask e_button = (GHOST_TButtonMask) i; + GHOST_TEventType e_action = (packet.pkButtons & mask) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; - // use older TabletData struct for testing until mine is in place - GHOST_TabletData& e_data = ((GHOST_TEventCursorData*) e->getData())->tablet; - e_data.Active = (GHOST_TTabletMode) data.tool.type; - e_data.Pressure = data.pressure; - e_data.Xtilt = data.tilt_x; - e_data.Ytilt = data.tilt_y; + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + GHOST_TabletData& e_data = ((GHOST_TEventButtonData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; -// system->pushEvent(e); + printf(" button %d %s\n", i, (e_action == GHOST_kEventButtonDown) ? "down" : "up"); + + system->pushEvent(e); + } } + + prevButtons = packet.pkButtons; + } + #endif + else + { + GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); + + // use older TabletData struct for testing until mine is in place + GHOST_TabletData& e_data = ((GHOST_TEventCursorData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; + + puts(" move"); + + system->pushEvent(e); } } } + return anyProcessed; } -void GHOST_TabletManagerWin32::changeTool(HCTX context, UINT serialNumber) +void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serialNumber) { puts("-- changing tool --"); dropTool(); - PACKET packet; - func_Packet(context, serialNumber, &packet); - UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - - // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); + HCTX context = contextForWindow(window); - switch (cursor) + if (context) { - case 0: // older Intuos tablets can track two cursors at once - case 3: // so we test for both here - activeTool.type = TABLET_MOUSE; - break; - case 1: - case 4: - activeTool.type = TABLET_PEN; - break; - case 2: - case 5: - activeTool.type = TABLET_ERASER; - break; - default: - activeTool.type = TABLET_NONE; + activeWindow = window; + + PACKET packet; + func_Packet(context, serialNumber, &packet); + UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; + + // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); + + switch (cursor) + { + case 0: // older Intuos tablets can track two cursors at once + case 3: // so we test for both here + activeTool.type = TABLET_MOUSE; + break; + case 1: + case 4: + activeTool.type = TABLET_PEN; + break; + case 2: + case 5: + activeTool.type = TABLET_ERASER; + break; + default: + activeTool.type = TABLET_NONE; + } + + WTPKT toolData; + func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; + // activeTool.hasTilt = toolData & tiltMask; + + if (activeTool.hasPressure) + puts(" - pressure"); + + if (activeTool.hasTilt) + puts(" - tilt"); + + // and just for fun: + if (toolData & PK_BUTTONS) + puts(" - buttons"); } - - WTPKT toolData; - func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData); - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; -// activeTool.hasTilt = toolData & tiltMask; - - if (activeTool.hasPressure) - puts(" - pressure"); - - if (activeTool.hasTilt) - puts(" - tilt"); - - // and just for fun: - if (toolData & PK_BUTTONS) - puts(" - buttons"); } void GHOST_TabletManagerWin32::dropTool() @@ -427,4 +501,7 @@ void GHOST_TabletManagerWin32::dropTool() activeTool.hasTilt = false; prevMouseX = prevMouseY = 0; + prevButtons = 0; + + activeWindow = NULL; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 290798a6bfb..c23c2bc3cb5 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -69,15 +69,16 @@ class GHOST_TabletManagerWin32 UINT cursorCount; UINT cursorBase; - // candidate for a base class: + // book-keeping + std::map contexts; + HCTX contextForWindow(GHOST_WindowWin32*); + + GHOST_WindowWin32* activeWindow; TabletTool activeTool; int prevMouseX; int prevMouseY; - - // book-keeping - std::map contexts; - HCTX contextForWindow(GHOST_WindowWin32*); + UINT prevButtons; void convertTilt(ORIENTATION const&, TabletToolData&); @@ -90,9 +91,11 @@ public: void openForWindow(GHOST_WindowWin32*); void closeForWindow(GHOST_WindowWin32*); - void processPackets(GHOST_WindowWin32*); + // returns whether any packets resulted in GHOST events + bool processPackets(GHOST_WindowWin32* = NULL); +// void processPacket(GHOST_WindowWin32*, UINT serialNumber); - void changeTool(HCTX, UINT serialNumber); + void changeTool(GHOST_WindowWin32*, UINT serialNumber); void dropTool(); }; @@ -100,10 +103,10 @@ public: The tablet manager is driven by the following Windows event processing code: case WT_PACKET: - m_tabletManager->processPackets((HCTX)lParam); + m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: - m_tabletManager->changeTool((HCTX)lParam, wParam); + m_tabletManager->changeTool(window, wParam); break; case WT_PROXIMITY: if (LOWORD(lParam) == 0) -- cgit v1.2.3 From 0473790bbeb24dd1fec1314f9a8e12b2fb155734 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 14 Aug 2010 23:33:22 +0000 Subject: removed gpencil Manhattan distance from user prefs. updated ghost build script. --- intern/ghost/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/ghost') diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index 65c00b16373..f6b818c0efc 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -11,7 +11,7 @@ if window_system == 'darwin': sources += env.Glob('intern/*.mm') -pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget'] +pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget','GHOST_TabletManager'] defs=['_USE_MATH_DEFINES'] if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6', 'aix4', 'aix5'): -- cgit v1.2.3 From 2c468d9e5a60b60ab70d1daabc3833d3e90d35eb Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 15 Aug 2010 11:02:03 +0000 Subject: Further hacking on Windows tablet code. More accurate detection of certain tablet tools (mice, etc.). Made tablet mouse/pen buttons play nice with GHOST. Removed old code from WindowWin32. --- intern/ghost/GHOST_IWindow.h | 10 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 13 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 299 +++++++++++++++++------ intern/ghost/intern/GHOST_TabletManagerWin32.h | 27 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 182 -------------- intern/ghost/intern/GHOST_WindowWin32.h | 33 --- 6 files changed, 254 insertions(+), 310 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 83757b17e8b..a6832868e8a 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -227,13 +227,15 @@ public: * @param data The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; - + /** * Returns the tablet data (pressure etc). * @return The tablet data (pressure etc). */ - virtual const GHOST_TabletData* GetTabletData() = 0; - + virtual const GHOST_TabletData* GetTabletData() + { return NULL; } + /* this function is targeted for removal by significant-bit */ + /*************************************************************************************** ** Progress bar functionality ***************************************************************************************/ @@ -304,8 +306,6 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) { return GHOST_kSuccess; }; - }; #endif // _GHOST_IWINDOW_H_ - diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 0f567dec4e2..11ba695a4f9 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -247,8 +247,12 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) } } while (waitForEvent && !anyProcessed); - if (m_tabletManager->processPackets()) - anyProcessed = true; +// Handle tablet input either here (polling) +// or after WT_PACKET messages (event driven) +// -- not both! + +// if (m_tabletManager->processPackets()) +// anyProcessed = true; return anyProcessed; } @@ -951,7 +955,6 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - puts("WT_PACKET"); m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: @@ -1011,7 +1014,9 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_MOUSEMOVE: { - if (!eventIsFromTablet()) + if (!eventIsFromTablet() && !m_tabletManager->anyButtonsDown()) + // Even with careful checking, a stray cursor event sneaks through just before each + // tablet mouse/pen button up event. Keep clean separation between tablet and mouse! { int xPrev = mousePosX; int yPrev = mousePosY; diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 9278ad2f48e..a34d6730cee 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -10,8 +10,8 @@ #include #include -#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION -#define PACKETMODE 0 /*PK_BUTTONS*/ +#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION) +#define PACKETMODE (0 /*PK_BUTTONS*/) // #define PACKETTILT PKEXT_ABSOLUTE #include "pktdef.h" @@ -31,6 +31,29 @@ static void print(AXIS const& t, char const* label = NULL) unitName[t.axUnits]); } +static void print(WTPKT packet) + { + if (packet == 0) + puts("- nothing special"); + else + { + if (packet & PK_CONTEXT) puts("- reporting context"); + if (packet & PK_STATUS) puts("- status bits"); + if (packet & PK_TIME) puts("- time stamp"); + if (packet & PK_CHANGED) puts("- change bit vector"); + if (packet & PK_SERIAL_NUMBER) puts("- packet serial number"); + if (packet & PK_CURSOR) puts("- reporting cursor"); + if (packet & PK_BUTTONS) puts("- buttons"); + if (packet & PK_X) puts("- x axis"); + if (packet & PK_Y) puts("- y axis"); + if (packet & PK_Z) puts("- z axis"); + if (packet & PK_NORMAL_PRESSURE) puts("- tip pressure"); + if (packet & PK_TANGENT_PRESSURE) puts("- barrel pressure"); + if (packet & PK_ORIENTATION) puts("- orientation/tilt"); + if (packet & PK_ROTATION) puts("- rotation"); + } + } + GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() : activeWindow(NULL) { @@ -49,40 +72,32 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); - WORD specV, implV; - func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); - func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); - printf("WinTab version %d.%d (%d.%d)\n", - HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); - - // query for overall capabilities and ranges - char tabletName[LC_NAMELEN]; - if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) - puts(tabletName); - - puts("active tablet area"); - AXIS xRange, yRange; - func_Info(WTI_DEVICES, DVC_X, &xRange); - func_Info(WTI_DEVICES, DVC_Y, &yRange); - print(xRange,"x"); print(yRange,"y"); - - + puts("\n-- essential tablet info --"); func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); - puts("pressure sensitivity"); + func_Info(WTI_DEVICES, DVC_PKTDATA, &allTools); + puts("\nall tools have"); print(allTools); + func_Info(WTI_DEVICES, DVC_CSRDATA, &someTools); + puts("some tools also have"); print(someTools); + + puts("\npressure sensitivity"); AXIS pressureRange; - hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);// && pressureRange.axMax != 0; - print(pressureRange); + hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE + && func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange); if (hasPressure) + { + print(pressureRange); pressureScale = 1.f / pressureRange.axMax; + } else pressureScale = 0.f; - puts("tilt sensitivity"); + puts("\ntilt sensitivity"); AXIS tiltRange[3]; - hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, tiltRange); + hasTilt = (allTools|someTools) & PK_ORIENTATION + && func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange); if (hasTilt) { @@ -103,7 +118,7 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() #if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed // this isn't working for [mce], so let it rest for now - printf("raw tilt sensitivity:\n"); + puts("\nraw tilt sensitivity"); hasTilt = false; UINT tag = 0; UINT extensionCount; @@ -135,6 +150,8 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() tiltScaleX = tiltScaleY = 0.f; } #endif // WTX_TILT + + getExtraInfo(); } } @@ -144,6 +161,83 @@ GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32() FreeLibrary(lib_Wintab); } +void GHOST_TabletManagerWin32::getExtraInfo() + { + puts("\n-- extra tablet info --"); + + WORD specV, implV; + func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); + func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); + printf("WinTab version %d.%d (%d.%d)\n", + HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); + + UINT ndevices, ncursors; + func_Info(WTI_INTERFACE, IFC_NDEVICES, &ndevices); + func_Info(WTI_INTERFACE, IFC_NCURSORS, &ncursors); + + printf("%d tablets, %d tools\n", ndevices, ncursors); + if (ndevices > 1) + ; // support this? + + // query for overall capabilities and ranges + char tabletName[LC_NAMELEN]; + if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) + puts(tabletName); + + puts("\nactive tablet area"); + AXIS xRange, yRange; + func_Info(WTI_DEVICES, DVC_X, &xRange); + func_Info(WTI_DEVICES, DVC_Y, &yRange); + print(xRange,"x"); print(yRange,"y"); + + putchar('\n'); + + UINT extensionCount; + func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); + for (UINT i = 0; i < extensionCount; ++i) + { + TCHAR name[40]; + func_Info(WTI_EXTENSIONS + i, EXT_NAME, name); + printf("extension %d: %s\n", i, name); + } + +// for (int i = cursorBase; i < cursorBase + cursorCount; ++i) + for (UINT i = 0; i < ncursors; ++i) + { + // what can each cursor do? + + UINT physID; + func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID); + if (physID == 0) + // each 'real' cursor has a physical ID + // (on Intuos at least, test on Graphire also) + continue; + + TCHAR name[40]; + func_Info(WTI_CURSORS + i, CSR_NAME, name); + printf("\ncursor %d: %s\n", i, name); + + BOOL active; + func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active); + printf("active: %s\n", active ? "yes" : "no"); + + WTPKT packet; + func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(packet & someTools); + + puts("buttons:"); + BYTE buttons; + BYTE sysButtonMap[32]; + func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons); + func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap); + for (int i = 0; i < buttons; ++i) + printf(" %d -> %d\n", i, sysButtonMap[i]); + } + + putchar('\n'); + } + bool GHOST_TabletManagerWin32::available() { return lib_Wintab // driver installed @@ -169,6 +263,7 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) LOGCONTEXT archetype; func_Info(WTI_DEFSYSCTX, 0, &archetype); // func_Info(WTI_DEFCONTEXT, 0, &archetype); +// func_Info(WTI_DSCTXS, 0, &archetype); strcpy(archetype.lcName, "blender special"); @@ -180,8 +275,8 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) archetype.lcPktData = packetData; archetype.lcPktMode = PACKETMODE; - archetype.lcOptions |= /*CXO_MESSAGES |*/ CXO_CSRMESSAGES; -// archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; +// archetype.lcOptions |= CXO_CSRMESSAGES; // <-- lean mean version + archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; #if PACKETMODE & PK_BUTTONS // we want first 5 buttons @@ -220,6 +315,7 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) printf("tablet queue size: %d\n", tabletQueueSize); contexts[window] = context; + activeWindow = window; } void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) @@ -231,6 +327,8 @@ void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) func_Close(context); // also remove it from our books: contexts.erase(contexts.find(window)); + if (activeWindow == window) + activeWindow = NULL; } } @@ -270,6 +368,28 @@ void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolDat data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; } +bool GHOST_TabletManagerWin32::convertButton(const UINT button, GHOST_TButtonMask& ghost) + { + switch (sysButtonMap[button]) + { + case 1: + ghost = GHOST_kButtonMaskLeft; + break; + case 4: + ghost = GHOST_kButtonMaskRight; + break; + case 7: + ghost = GHOST_kButtonMaskMiddle; + break; + // sorry, no Button4 or Button5 + // they each map to 0 (unused) + default: + return false; + }; + + return true; + } + bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { if (window == NULL) @@ -305,7 +425,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) anyProcessed = true; - // Since we're using a digitizing context, we need to + // If we're using a digitizing context, we need to // move the on-screen cursor ourselves. // SetCursorPos(x, y); @@ -344,8 +464,6 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) if (o.orAzimuth || o.orAltitude) { convertTilt(o, data); - printf(" /%d,%d/", o.orAzimuth, o.orAltitude); - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) { // really should fix the initial test for activeTool.hasTilt, @@ -354,6 +472,11 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) data.tilt_x = 0.f; data.tilt_y = 0.f; } + else + { + // printf(" /%d,%d/", o.orAzimuth, o.orAltitude); + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + } } else data.tool.hasTilt = false; @@ -367,8 +490,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); // any buttons changed? - #if PACKETMODE & PK_BUTTONS - // relative buttons mode + #if PACKETMODE & PK_BUTTONS // relative buttons mode if (packet.pkButtons) { // which button? @@ -390,8 +512,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) system->pushEvent(e); } - #else - // absolute buttons mode + #else // absolute buttons mode UINT diff = prevButtons ^ packet.pkButtons; if (diff) { @@ -401,19 +522,23 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) if (diff & mask) { - GHOST_TButtonMask e_button = (GHOST_TButtonMask) i; - GHOST_TEventType e_action = (packet.pkButtons & mask) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; - - GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); - GHOST_TabletData& e_data = ((GHOST_TEventButtonData*) e->getData())->tablet; - e_data.Active = (GHOST_TTabletMode) data.tool.type; - e_data.Pressure = data.pressure; - e_data.Xtilt = data.tilt_x; - e_data.Ytilt = data.tilt_y; - - printf(" button %d %s\n", i, (e_action == GHOST_kEventButtonDown) ? "down" : "up"); - - system->pushEvent(e); + GHOST_TButtonMask e_button; + if (convertButton(i, e_button)) + { + GHOST_TEventType e_action = (packet.pkButtons & mask) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; + + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + GHOST_TabletData& e_data = ((GHOST_TEventButtonData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; + + printf(" button %d %s\n", i, (e_action == GHOST_kEventButtonDown) ? "down" : "up"); + + system->pushEvent(e); + } + else puts(" mystery button (discarded)"); } } @@ -451,14 +576,14 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial if (context) { activeWindow = window; - + PACKET packet; func_Packet(context, serialNumber, &packet); - UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - - // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); - - switch (cursor) + + // try one way to classify cursor + UINT cursorType = (packet.pkCursor - cursorBase) % cursorCount; + printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursorType); + switch (cursorType) { case 0: // older Intuos tablets can track two cursors at once case 3: // so we test for both here @@ -475,22 +600,55 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial default: activeTool.type = TABLET_NONE; } - + + // now try another way + func_Info(WTI_CURSORS + packet.pkCursor, CSR_TYPE, &cursorType); + switch (cursorType & 0xf06) + { + case 0x802: + puts("general stylus"); + break; + case 0x902: + puts("airbrush"); + break; + case 0x804: + puts("art pen"); + break; + case 0x004: + puts("4D mouse"); + break; + case 0x006: + puts("5-button puck"); + break; + default: + puts("???"); + } + WTPKT toolData; func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; - // activeTool.hasTilt = toolData & tiltMask; - - if (activeTool.hasPressure) - puts(" - pressure"); - - if (activeTool.hasTilt) - puts(" - tilt"); - - // and just for fun: - if (toolData & PK_BUTTONS) - puts(" - buttons"); + // discard any stray capabilities + // (sometimes cursors claim to be able to do things + // that their tablet doesn't support) + toolData &= (allTools|someTools); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(toolData & someTools); + putchar('\n'); + + if (activeTool.type == TABLET_MOUSE) + { + // don't always trust CSR_PKTDATA! + activeTool.hasPressure = false; + activeTool.hasTilt = false; + } + else + { + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; + // activeTool.hasTilt = toolData & tiltMask; + } + + // remember user's custom button assignments for this tool + func_Info(WTI_CURSORS + packet.pkCursor, CSR_SYSBTNMAP, sysButtonMap); } } @@ -505,3 +663,8 @@ void GHOST_TabletManagerWin32::dropTool() activeWindow = NULL; } + +bool GHOST_TabletManagerWin32::anyButtonsDown() + { + return prevButtons != 0; + } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index c23c2bc3cb5..835711bb6c4 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -10,6 +10,7 @@ #include "wintab.h" #include +#include "GHOST_Types.h" class GHOST_WindowWin32; // BEGIN from Wacom's Utils.h @@ -57,6 +58,8 @@ class GHOST_TabletManagerWin32 WTPACKETSGET func_PacketsGet; WTPACKET func_Packet; + void getExtraInfo(); // to help support new/untested tablets + // tablet attributes bool hasPressure; float pressureScale; @@ -68,6 +71,8 @@ class GHOST_TabletManagerWin32 // UINT tiltMask; UINT cursorCount; UINT cursorBase; + WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) + WTPKT someTools; // extra info available from only some tools // book-keeping std::map contexts; @@ -75,12 +80,14 @@ class GHOST_TabletManagerWin32 GHOST_WindowWin32* activeWindow; TabletTool activeTool; + BYTE sysButtonMap[32]; // user's custom button assignments for active tool int prevMouseX; int prevMouseY; UINT prevButtons; void convertTilt(ORIENTATION const&, TabletToolData&); + bool convertButton(const UINT button, GHOST_TButtonMask&); public: GHOST_TabletManagerWin32(); @@ -97,24 +104,8 @@ public: void changeTool(GHOST_WindowWin32*, UINT serialNumber); void dropTool(); - }; -/* -The tablet manager is driven by the following Windows event processing code: - -case WT_PACKET: - m_tabletManager->processPackets(window); - break; -case WT_CSRCHANGE: - m_tabletManager->changeTool(window, wParam); - break; -case WT_PROXIMITY: - if (LOWORD(lParam) == 0) - { - puts("-- dropping tool --"); - m_tabletManager->dropTool(); - } - break; -*/ + bool anyButtonsDown(); + }; #endif diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 361223a2cc8..98609926fe8 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -125,10 +125,6 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_hasMouseCaptured(false), m_nPressedButtons(0), m_customCursor(0), -// m_wintab(false), -// m_tabletData(NULL), -// m_tablet(0), -// m_maxPressure(0), m_multisample(numOfAASamples), m_multisampleEnabled(msEnabled), m_msPixelFormat(msPixelFormat), @@ -236,83 +232,11 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_hWnd = 0; } } - -#if 0 - m_wintab = LoadWintab(); - if (m_wintab) { - // let's see if we can initialize tablet here - /* check if WinTab available. */ - if (gpWTInfoA(0, 0, NULL)) { - // Now init the tablet - LOGCONTEXT lc; - AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */ - - // Open a Wintab context - - // Get default context information - gpWTInfoA( WTI_DEFCONTEXT, 0, &lc ); - - // Open the context - lc.lcPktData = PACKETDATA; - lc.lcPktMode = PACKETMODE; - lc.lcOptions |= /* CXO_MESSAGES | */ CXO_SYSTEM; - lc.lcOptions &= ~CXO_MESSAGES; - - /* Set the entire tablet as active */ - gpWTInfoA(WTI_DEVICES,DVC_X,&TabletX); - gpWTInfoA(WTI_DEVICES,DVC_Y,&TabletY); - - /* get the max pressure, to divide into a float */ - BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); - if (pressureSupport) - m_maxPressure = Pressure.axMax; - else - m_maxPressure = 0; - - /* get the max tilt axes, to divide into floats */ - BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); - if (tiltSupport) { - /* does the tablet support azimuth ([0]) and altitude ([1]) */ - if (Orientation[0].axResolution && Orientation[1].axResolution) { - /* all this assumes the minimum is 0 */ - m_maxAzimuth = Orientation[0].axMax; - m_maxAltitude = Orientation[1].axMax; - } - else { /* no so dont do tilt stuff */ - m_maxAzimuth = m_maxAltitude = 0; - } - } - - m_tablet = gpWTOpenA( m_hWnd, &lc, TRUE ); - if (m_tablet) { - m_tabletData = new GHOST_TabletData(); - m_tabletData->Active = GHOST_kTabletModeNone; - - // request a deep queue, to capture every pen point - int tabletQueueSize = 128; - while (!gpWTQueueSizeSet(m_tablet, tabletQueueSize)) - --tabletQueueSize; - printf("tablet queue size: %d\n", tabletQueueSize); - } - } - } -#endif } GHOST_WindowWin32::~GHOST_WindowWin32() { -#if 0 - if (m_wintab) { - if (m_tablet) - gpWTClose(m_tablet); - if (m_tabletData) - delete m_tabletData; - m_tabletData = NULL; - UnloadWintab(); - } -#endif - if (m_tabletManager) m_tabletManager->closeForWindow(this); @@ -922,112 +846,6 @@ void GHOST_WindowWin32::becomeTabletAware(GHOST_TabletManagerWin32* manager) m_tabletManager->openForWindow(this); } -#if 0 -void GHOST_WindowWin32::processWin32TabletInitEvent() -{ - if (m_wintab) { - // let's see if we can initialize tablet here - AXIS Pressure, Orientation[3]; /* The maximum tablet size */ - - BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); - if (pressureSupport) - m_maxPressure = Pressure.axMax; - else - m_maxPressure = 0; - - BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); - if (tiltSupport) { - /* does the tablet support azimuth ([0]) and altitude ([1]) */ - if (Orientation[0].axResolution && Orientation[1].axResolution) { - m_maxAzimuth = Orientation[0].axMax; - m_maxAltitude = Orientation[1].axMax; - } - else { /* no so dont do tilt stuff */ - m_maxAzimuth = m_maxAltitude = 0; - } - } - - m_tabletData->Active = GHOST_kTabletModeNone; - } -} - -void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) -{ -// PACKET pkt; - if (m_wintab) { - printf("tablet event "); - PACKET pkt_buffer[128]; - int n = gpWTPacketsGet((HCTX)lParam, 128, pkt_buffer); - printf("(%d in queue) ", n); - for (int i = 0; i < n; ++i) { - PACKET& pkt = pkt_buffer[i]; - // "while" not "if" -- drain the queue! -// while (gpWTPacket((HCTX)lParam, wParam, &pkt)) { - putchar('.'); - if (m_tabletData) { - switch (pkt.pkCursor) { - case 0: /* first device */ - case 3: /* second device */ - m_tabletData->Active = GHOST_kTabletModeNone; /* puck - not yet supported */ - break; - case 1: - case 4: - m_tabletData->Active = GHOST_kTabletModeStylus; /* stylus */ - break; - case 2: - case 5: - m_tabletData->Active = GHOST_kTabletModeEraser; /* eraser */ - break; - } - if (m_maxPressure > 0) { - m_tabletData->Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure; - } else { - m_tabletData->Pressure = 1.0f; - } - - if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) { - ORIENTATION ort = pkt.pkOrientation; - float vecLen; - float altRad, azmRad; /* in radians */ - - /* - from the wintab spec: - orAzimuth Specifies the clockwise rotation of the - cursor about the z axis through a full circular range. - - orAltitude Specifies the angle with the x-y plane - through a signed, semicircular range. Positive values - specify an angle upward toward the positive z axis; - negative values specify an angle downward toward the negative z axis. - - wintab.h defines .orAltitude as a UINT but documents .orAltitude - as positive for upward angles and negative for downward angles. - WACOM uses negative altitude values to show that the pen is inverted; - therefore we cast .orAltitude as an (int) and then use the absolute value. - */ - - /* convert raw fixed point data to radians */ - altRad = (float)((fabs((float)ort.orAltitude)/(float)m_maxAltitude) * M_PI/2.0); - azmRad = (float)(((float)ort.orAzimuth/(float)m_maxAzimuth) * M_PI*2.0); - - /* find length of the stylus' projected vector on the XY plane */ - vecLen = cos(altRad); - - /* from there calculate X and Y components based on azimuth */ - m_tabletData->Xtilt = sin(azmRad) * vecLen; - m_tabletData->Ytilt = (float)(sin(M_PI/2.0 - azmRad) * vecLen); - - } else { - m_tabletData->Xtilt = 0.0f; - m_tabletData->Ytilt = 0.0f; - } - } - } - putchar('\n'); - } -} -#endif - /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 6cb68d2ff52..9b2a89cfa2f 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -43,25 +43,10 @@ #define WIN32_LEAN_AND_MEAN #include -/* -#include -#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) -#define PACKETMODE PK_BUTTONS -#include -*/ - class GHOST_SystemWin32; class GHOST_DropTargetWin32; class GHOST_TabletManagerWin32; -/* -// typedefs for WinTab functions to allow dynamic loading -typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID ); -typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL); -typedef BOOL (API * GHOST_WIN32_WTClose) (HCTX); -typedef BOOL (API * GHOST_WIN32_WTPacket) (HCTX, UINT, LPVOID); -*/ - /** * GHOST window on M$ Windows OSs. * @author Maarten Gribnau @@ -250,12 +235,6 @@ public: */ void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; - const GHOST_TabletData* GetTabletData() - { return NULL; /*m_tabletData;*/ } - -// void processWin32TabletInitEvent(); -// void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); - void becomeTabletAware(GHOST_TabletManagerWin32*); protected: @@ -347,18 +326,6 @@ protected: static LPCSTR s_windowClassName; static const int s_maxTitleLength; - /** WinTab dll handle */ -// HMODULE m_wintab; -// bool m_wintab; - - /** Tablet data for GHOST */ -// GHOST_TabletData* m_tabletData; - - /** Stores the Tablet context if detected Tablet features using WinTab.dll */ -// HCTX m_tablet; -// LONG m_maxPressure; -// LONG m_maxAzimuth, m_maxAltitude; - /** Preferred number of samples */ GHOST_TUns16 m_multisample; -- cgit v1.2.3 From 4bfd915f9c1e2de30617683e2415d6d65bda4627 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 16 Aug 2010 18:59:36 +0000 Subject: pencils down! additional Windows Wacom wackiness. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 27 ++++-- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 111 ++++++++++++++++++----- intern/ghost/intern/GHOST_TabletManagerWin32.h | 33 ++++++- 3 files changed, 138 insertions(+), 33 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 11ba695a4f9..0315fa5870a 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -841,7 +841,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam) { GHOST_Event* event = NULL; - bool eventSent = false; + bool eventHandled = false; static int mousePosX = 0, mousePosY = 0; // track mouse position between calls @@ -1014,10 +1014,19 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_MOUSEMOVE: { - if (!eventIsFromTablet() && !m_tabletManager->anyButtonsDown()) + if (!eventIsFromTablet()) + { // Even with careful checking, a stray cursor event sneaks through just before each // tablet mouse/pen button up event. Keep clean separation between tablet and mouse! - { + if (m_tabletManager->anyButtonsDown()) + { + // tablet manager handles all its own cursor moves. + // ignore 'regular' mouse while a tablet tool is being used. + DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam); + eventHandled = true; + break; + } + int xPrev = mousePosX; int yPrev = mousePosY; // window coordinates are passed in via lParam @@ -1056,10 +1065,10 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM UINT rawSize = sizeof(RAWINPUT); GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); - eventSent |= processRawInput(raw, window); + eventHandled |= processRawInput(raw, window); if (processRawInput(raw, window)) - eventSent = true; + eventHandled = true; // else // DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); @@ -1089,7 +1098,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM for (int i = 0; i < n; ++i) { RAWINPUT const& raw = rawBuffer[i]; - eventSent |= processRawInput(raw, window); + eventHandled |= processRawInput(raw, window); } // clear processed events from the queue @@ -1290,13 +1299,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM #endif // illustrative code } - if (!eventSent) + if (!eventHandled) if (event) { pushEvent(event); - eventSent = true; + eventHandled = true; } - return eventSent; + return eventHandled; } GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index a34d6730cee..868b5dcc162 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -171,27 +171,6 @@ void GHOST_TabletManagerWin32::getExtraInfo() printf("WinTab version %d.%d (%d.%d)\n", HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); - UINT ndevices, ncursors; - func_Info(WTI_INTERFACE, IFC_NDEVICES, &ndevices); - func_Info(WTI_INTERFACE, IFC_NCURSORS, &ncursors); - - printf("%d tablets, %d tools\n", ndevices, ncursors); - if (ndevices > 1) - ; // support this? - - // query for overall capabilities and ranges - char tabletName[LC_NAMELEN]; - if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) - puts(tabletName); - - puts("\nactive tablet area"); - AXIS xRange, yRange; - func_Info(WTI_DEVICES, DVC_X, &xRange); - func_Info(WTI_DEVICES, DVC_Y, &yRange); - print(xRange,"x"); print(yRange,"y"); - - putchar('\n'); - UINT extensionCount; func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); for (UINT i = 0; i < extensionCount; ++i) @@ -201,8 +180,84 @@ void GHOST_TabletManagerWin32::getExtraInfo() printf("extension %d: %s\n", i, name); } -// for (int i = cursorBase; i < cursorBase + cursorCount; ++i) - for (UINT i = 0; i < ncursors; ++i) + UINT deviceCount, cursorCount; + func_Info(WTI_INTERFACE, IFC_NDEVICES, &deviceCount); + func_Info(WTI_INTERFACE, IFC_NCURSORS, &cursorCount); + + printf("%d tablets, %d tools\n", deviceCount, cursorCount); + if (deviceCount > 1) + ; // support this? + + for (UINT i = 0; i < deviceCount; ++i) + { + Tablet tablet; + + // query for overall capabilities and ranges + char tabletName[LC_NAMELEN]; + if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) + printf("tablet %d: %s\n", i, tabletName); + + puts("\nactive tablet area"); + AXIS xRange, yRange; + func_Info(WTI_DEVICES + i, DVC_X, &xRange); + func_Info(WTI_DEVICES + i, DVC_Y, &yRange); + tablet.size_x = xRange.axMax; + tablet.size_y = yRange.axMax; + print(xRange,"x"); print(yRange,"y"); + + func_Info(WTI_DEVICES + i, DVC_NCSRTYPES, &cursorCount); + func_Info(WTI_DEVICES + i, DVC_FIRSTCSR, &cursorBase); + tablet.cursorBase = cursorBase; + tablet.cursorCount = cursorCount; + printf("owns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1); + + func_Info(WTI_DEVICES + i, DVC_PKTDATA, &allTools); + puts("\nall tools have"); print(allTools); + func_Info(WTI_DEVICES + i, DVC_CSRDATA, &someTools); + puts("some tools also have"); print(someTools); + + puts("\npressure sensitivity"); + AXIS pressureRange; + hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE + && func_Info(WTI_DEVICES + i, DVC_NPRESSURE, &pressureRange); + + if (hasPressure) + { + print(pressureRange); + pressureScale = 1.f / pressureRange.axMax; + } + else + pressureScale = 0.f; + + puts("\ntilt sensitivity"); + AXIS tiltRange[3]; + hasTilt = (allTools|someTools) & PK_ORIENTATION + && func_Info(WTI_DEVICES + i, DVC_ORIENTATION, &tiltRange); + + if (hasTilt) + { + // leave this code in place to help support tablets I haven't tested + const char* axisName[] = {"azimuth","altitude","twist"}; + for (int i = 0; i < 3; ++i) + print(tiltRange[i], axisName[i]); + + // cheat by using available data from Intuos4. test on other tablets!!! + // azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); + // altitudeScale = 1.f / tiltRange[1].axMax; + + azimuthScale = 1.f / tiltRange[0].axMax; + altitudeScale = 1.f / tiltRange[1].axMax; + } + else + { + puts("none"); + azimuthScale = altitudeScale = 0.f; + } + + tablets.push_back(tablet); + } + + for (UINT i = 0; i < cursorCount; ++i) { // what can each cursor do? @@ -415,6 +470,13 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) int y = packet.pkY; if (activeTool.type == TABLET_MOUSE) + { + // until scaling is working better, use system cursor position instead + POINT systemPos; + GetCursorPos(&systemPos); + x = systemPos.x; + y = systemPos.y; + if (x == prevMouseX && y == prevMouseY && packet.pkButtons == prevButtons) // don't send any "mouse hasn't moved" events continue; @@ -422,6 +484,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) prevMouseX = x; prevMouseY = y; } + } anyProcessed = true; @@ -601,6 +664,7 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial activeTool.type = TABLET_NONE; } +//#if 0 // now try another way func_Info(WTI_CURSORS + packet.pkCursor, CSR_TYPE, &cursorType); switch (cursorType & 0xf06) @@ -623,6 +687,7 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial default: puts("???"); } +//#endif WTPKT toolData; func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 835711bb6c4..df6f43d0460 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -9,6 +9,7 @@ #include #include "wintab.h" #include +#include #include "GHOST_Types.h" class GHOST_WindowWin32; @@ -22,6 +23,10 @@ typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); // END +// TabletToolData (and its components) are meant to replace GHOST_TabletData +// and its customdata analogue in the window manager. For now it's confined to the +// TabletManager. + typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType; typedef struct @@ -31,7 +36,7 @@ typedef struct // capabilities bool hasPressure : 1; bool hasTilt : 1; - + } TabletTool; @@ -45,6 +50,30 @@ typedef struct } TabletToolData; +// "Tablet" structure is not active by pencils down +// but will be soon. + +struct Tablet + { + bool hasPressure; + float pressureScale; + + bool hasTilt; + float azimuthScale; + float altitudeScale; + + UINT size_x, size_y; + + UINT cursorCount; + UINT cursorBase; + + WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) + WTPKT someTools; // extra info available from only some tools + + bool ownsCursor(UINT x) + { return (x - cursorBase) < cursorCount; } + }; + class GHOST_TabletManagerWin32 { // the Wintab library @@ -78,6 +107,8 @@ class GHOST_TabletManagerWin32 std::map contexts; HCTX contextForWindow(GHOST_WindowWin32*); + std::vector tablets; + GHOST_WindowWin32* activeWindow; TabletTool activeTool; BYTE sysButtonMap[32]; // user's custom button assignments for active tool -- cgit v1.2.3 From a7f2cbc88f4e55fb3ed7b5ba54383d38acea089b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 14 Dec 2010 22:43:52 +0000 Subject: As-yet uncommitted changes from end of summer. General code cleanup Mac-side, removed some unnecessary NSAutoreleasePool guards, etc. By no means complete -- just wanted to get this in and do a fresh checkout on another machine. --- intern/ghost/GHOST_ISystem.h | 2 +- intern/ghost/intern/GHOST_Buttons.cpp | 47 ++- intern/ghost/intern/GHOST_SystemCocoa.h | 276 ++++++++-------- intern/ghost/intern/GHOST_SystemCocoa.mm | 94 +----- intern/ghost/intern/GHOST_WindowCocoa.h | 171 +++++----- intern/ghost/intern/GHOST_WindowCocoa.mm | 523 ++++++++++++++----------------- 6 files changed, 499 insertions(+), 614 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index b759b98f0bc..c0a9defaaae 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -27,7 +27,7 @@ */ /** * @file GHOST_ISystem.h - * Main interface file for C++ Api with declaration of GHOST_ISystem interface + * Main interface file for C++ API with declaration of GHOST_ISystem interface * class. * Contains the doxygen documentation main page. */ diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp index 5a1f5dea430..87b0813648b 100644 --- a/intern/ghost/intern/GHOST_Buttons.cpp +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -29,7 +29,6 @@ #include "GHOST_Buttons.h" - GHOST_Buttons::GHOST_Buttons() { clear(); @@ -39,37 +38,37 @@ GHOST_Buttons::~GHOST_Buttons() {} bool GHOST_Buttons::get(GHOST_TButtonMask mask) const { - switch (mask) { - case GHOST_kButtonMaskLeft: - return m_ButtonLeft; - case GHOST_kButtonMaskMiddle: - return m_ButtonMiddle; - case GHOST_kButtonMaskRight: - return m_ButtonRight; - default: - return false; - } + switch (mask) { + case GHOST_kButtonMaskLeft: + return m_ButtonLeft; + case GHOST_kButtonMaskMiddle: + return m_ButtonMiddle; + case GHOST_kButtonMaskRight: + return m_ButtonRight; + default: + return false; + } } void GHOST_Buttons::set(GHOST_TButtonMask mask, bool down) { - switch (mask) { - case GHOST_kButtonMaskLeft: - m_ButtonLeft = down; break; - case GHOST_kButtonMaskMiddle: - m_ButtonMiddle = down; break; - case GHOST_kButtonMaskRight: - m_ButtonRight = down; break; - default: - break; - } + switch (mask) { + case GHOST_kButtonMaskLeft: + m_ButtonLeft = down; break; + case GHOST_kButtonMaskMiddle: + m_ButtonMiddle = down; break; + case GHOST_kButtonMaskRight: + m_ButtonRight = down; break; + default: + break; + } } void GHOST_Buttons::clear() { - m_ButtonLeft = false; - m_ButtonMiddle = false; - m_ButtonRight = false; + m_ButtonLeft = false; + m_ButtonMiddle = false; + m_ButtonRight = false; } bool GHOST_Buttons::anyDown() const diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index c84c69707ad..de835ad7768 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -21,13 +21,14 @@ * * The Original Code is: all of this file. * - * Contributor(s): Maarten Gribnau 05/2001 - * Damien Plisson 09/2009 + * Contributor(s): Maarten Gribnau 05/2001 + * Damien Plisson 09/2009 * * ***** END GPL LICENSE BLOCK ***** */ + /** - * @file GHOST_SystemCocoa.h + * @file GHOST_SystemCocoa.h * Declaration of GHOST_SystemCocoa class. */ @@ -44,20 +45,20 @@ class GHOST_EventCursor; class GHOST_EventKey; class GHOST_EventWindow; class GHOST_WindowCocoa; - +class NSAutoreleasePool; // actually Obj-C, but GHOST_ISystem.cpp doesn't understand @class syntax class GHOST_SystemCocoa : public GHOST_System { public: - /** - * Constructor. - */ - GHOST_SystemCocoa(); - - /** - * Destructor. - */ - ~GHOST_SystemCocoa(); - + /** + * Constructor. + */ + GHOST_SystemCocoa(); + + /** + * Destructor. + */ + ~GHOST_SystemCocoa(); + /*************************************************************************************** ** Time(r) functionality ***************************************************************************************/ @@ -68,7 +69,7 @@ public: * Based on ANSI clock() routine. * @return The number of milliseconds. */ - virtual GHOST_TUns64 getMilliSeconds() const; + GHOST_TUns64 getMilliSeconds() const; /*************************************************************************************** ** Display/window management functionality @@ -78,31 +79,30 @@ public: * Returns the number of displays on this system. * @return The number of displays. */ - virtual GHOST_TUns8 getNumDisplays() const; + GHOST_TUns8 getNumDisplays() const; /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. */ - virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; - + void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; + /** * Create a new window. - * The new window is added to the list of windows managed. + * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) + * @param parentWindow Parent (embedder) window + * @return The new window (or 0 if creation failed). */ - virtual GHOST_IWindow* createWindow( + GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, @@ -114,166 +114,166 @@ public: const GHOST_TUns16 numOfAASamples = 0, const GHOST_TEmbedderWindowID parentWindow = 0 ); - - virtual GHOST_TSuccess beginFullScreen( + + GHOST_TSuccess beginFullScreen( const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual ); - - virtual GHOST_TSuccess endFullScreen( void ); - + + GHOST_TSuccess endFullScreen( void ); + /*************************************************************************************** ** Event management functionality ***************************************************************************************/ /** * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. */ - virtual bool processEvents(bool waitForEvent); - + bool processEvents(bool waitForEvent); + /** * Handle User request to quit, from Menu bar Quit, and Cmd+Q * Display alert panel if changes performed since last save */ GHOST_TUns8 handleQuitRequest(); - + /** * Handle Cocoa openFile event * Display confirmation request panel if changes performed since last save */ - bool handleOpenDocumentRequest(void *filepathStr); - + bool handleOpenDocumentRequest(void *filepathStr); + /** - * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass - * @param eventType The type of drag'n'drop event - * @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) - * @param mouseX x mouse coordinate (in cocoa base window coordinates) - * @param mouseY y mouse coordinate - * @param window The window on which the event occurred - * @return Indication whether the event was handled. - */ + * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass + * @param eventType The type of drag'n'drop event + * @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) + * @param mouseX x mouse coordinate (in cocoa base window coordinates) + * @param mouseY y mouse coordinate + * @param window The window on which the event occurred + * @return Indication whether the event was handled. + */ GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, - GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data); - + GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data); + /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ /** * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. */ - virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; + GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; /** * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. */ - virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); - + GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + /*************************************************************************************** ** Access to mouse button and keyboard states. ***************************************************************************************/ /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. */ - virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; + GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * @param buttons The state of the buttons. + * @return Indication of success. */ - virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; + GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; /** * Returns Clipboard data - * @param selection Indicate which buffer to return - * @return Returns the selected buffer + * @param selection Indicate which buffer to return + * @return Returns the selected buffer */ - virtual GHOST_TUns8* getClipboard(bool selection) const; - + GHOST_TUns8* getClipboard(bool selection) const; + /** * Puts buffer to system clipboard - * @param buffer The buffer to be copied - * @param selection Indicates which buffer to copy too, only used on X11 + * @param buffer The buffer to be copied + * @param selection Indicates which buffer to copy too, only used on X11 */ - virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, not including versioning. * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ - virtual const GHOST_TUns8* getSystemDir() const; + const GHOST_TUns8* getSystemDir() const; /** * Determine the base dir in which user configuration is stored, not including versioning. * If needed, it will create the base directory. * @return Unsigned char string pointing to user dir (eg ~/.blender/). */ - virtual const GHOST_TUns8* getUserDir() const; + const GHOST_TUns8* getUserDir() const; /** - * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir - */ - virtual const GHOST_TUns8* getBinaryDir() const; + * Determine the directory of the current binary + * @return Unsigned char string pointing to the binary dir + */ + const GHOST_TUns8* getBinaryDir() const; /** - * Handles a window event. Called by GHOST_WindowCocoa window delegate - * @param eventType The type of window event - * @param window The window on which the event occurred - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); + * Handles a window event. Called by GHOST_WindowCocoa window delegate + * @param eventType The type of window event + * @param window The window on which the event occurred + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); /** - * Handles the Cocoa event telling the application has become active (again) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleApplicationBecomeActiveEvent(); + * Handles the Cocoa event telling the application has become active (again) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleApplicationBecomeActiveEvent(); /** - * External objects should call this when they send an event outside processEvents. - */ + * External objects should call this when they send an event outside processEvents. + */ void notifyExternalEventProcessed(); protected: /** * Initializes the system. * For now, it justs registers the window class (WNDCLASS). - * @return A success value. + * @return A success value. + */ + GHOST_TSuccess init(); + + /** + * Handles a tablet pen event. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleTabletEvent(void *eventPtr); + + /** + * Helps handleTabletEvent function. */ - virtual GHOST_TSuccess init(); - - /** - * Handles a tablet pen event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleTabletEvent(void *eventPtr); - - /** - * Helps handleTabletEvent function. - */ void fillTabletData(GHOST_TabletData& tablet, void* event_ptr); /** - * Handles a tablet proximity event. Sets pen or mouse ID for later events. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ + * Handles a tablet proximity event. Sets pen or mouse ID for later events. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ GHOST_TSuccess handleTabletProximity(void *eventPtr); /** Tablet Mouse and Pen IDs, used to correlate events with the tool that caused them. */ @@ -286,24 +286,24 @@ protected: GHOST_TTabletMode m_tablet_pen_mode; /** - * Handles a mouse event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleMouseEvent(void *eventPtr); - - /** - * Handles a key event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleKeyEvent(void *eventPtr); - + * Handles a mouse event. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleMouseEvent(void *eventPtr); + + /** + * Handles a key event. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleKeyEvent(void *eventPtr); + /** * Performs the actual cursor position update (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. */ GHOST_TSuccess setMouseCursorPosition(float x, float y); @@ -313,29 +313,31 @@ protected: /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; - + /** Raised window is not yet known by the window manager, so delay application become active event handling */ bool m_needDelayedApplicationBecomeActiveEventProcessing; - + /** Mouse buttons state */ GHOST_TUns32 m_pressedMouseButtons; - - /** State of the modifiers. */ - GHOST_TUns32 m_modifierMask; - /** Ignores window size messages (when window is dragged). */ - bool m_ignoreWindowSizedMessages; - + /** State of the modifiers. */ + GHOST_TUns32 m_modifierMask; + + /** Ignores window size messages (when window is dragged). */ + bool m_ignoreWindowSizedMessages; + /** Stores the mouse cursor delta due to setting a new cursor position * Needed because cocoa event delta cursor move takes setCursorPosition changes too. */ GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y; - + /** Multitouch trackpad availability */ bool m_hasMultiTouchTrackpad; - + /** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */ bool m_isGestureInProgress; + + NSAutoreleasePool* m_pool; }; #endif // _GHOST_SYSTEM_COCOA_H_ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index b0c7f10f329..2075058b32e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -466,19 +466,12 @@ extern "C" { struct bContext; struct wmOperator; extern int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op); - - -int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) -{ - int result; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - result = fromcocoa_request_qtcodec_settings(C, op); - - [pool drain]; - return result; -} -}; + + int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) + { + return fromcocoa_request_qtcodec_settings(C, op); + } +} // "C" #endif @@ -541,6 +534,8 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) GHOST_SystemCocoa::GHOST_SystemCocoa() { + m_pool = [[NSAutoreleasePool alloc] init]; + int mib[2]; struct timeval boottime; size_t len; @@ -556,7 +551,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() m_tablet_pen_mode = GHOST_kTabletModeNone; m_outsideLoopEventProcessed = false; m_needDelayedApplicationBecomeActiveEventProcessing = false; - m_displayManager = new GHOST_DisplayManagerCocoa (); + m_displayManager = new GHOST_DisplayManagerCocoa; GHOST_ASSERT(m_displayManager, "GHOST_SystemCocoa::GHOST_SystemCocoa(): m_displayManager==0\n"); m_displayManager->initialize(); @@ -602,7 +597,6 @@ GHOST_TSuccess GHOST_SystemCocoa::init() m_ndofManager = new GHOST_NDOFManagerCocoa(*this); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { [NSApplication sharedApplication]; @@ -666,8 +660,6 @@ GHOST_TSuccess GHOST_SystemCocoa::init() } [NSApp finishLaunching]; - - [pool drain]; } return success; } @@ -696,18 +688,12 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const { //Note that OS X supports monitor hot plug // We do not support multiple monitors at the moment - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - GHOST_TUns8 count = [[NSScreen screens] count]; - - [pool drain]; - return count; + return [[NSScreen screens] count]; } void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; @@ -717,8 +703,6 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns width = contentRect.size.width; height = contentRect.size.height; - - [pool drain]; } @@ -735,7 +719,6 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( const GHOST_TEmbedderWindowID parentWindow ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_IWindow* window = 0; //Get the available rect for including window contents @@ -768,7 +751,6 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n"); } - [pool drain]; return window; } @@ -789,8 +771,6 @@ GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void) return currentWindow->setState(GHOST_kWindowStateNormal); } - - /** * @note : returns coordinates in Cocoa screen coordinates @@ -835,7 +815,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow(); if (!window) return GHOST_kFailure; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSScreen *windowScreen = window->getScreen(); NSRect screenRect = [windowScreen frame]; @@ -848,7 +828,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf)); - [pool drain]; +// [pool drain]; return GHOST_kSuccess; } @@ -995,8 +975,6 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) } } while (event != nil); - [pool drain]; - if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); @@ -1005,6 +983,9 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) return true; } + [pool drain]; // for this event processing thread + [m_pool drain]; // for main thread + return anyProcessed; } @@ -1404,9 +1385,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) return GHOST_kFailure; } -// don't involve the window! -// GHOST_TabletData& ct = window->GetCocoaTabletData(); - GHOST_TTabletMode active_tool; int* tool_id_ptr; @@ -1438,11 +1416,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) m_tablet_pen_mode = active_tool; -// ct.Active = active_tool; -// ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0; -// ct.Xtilt = 0; -// ct.Ytilt = 0; - // this is a good place to remember the tool's capabilities } else { @@ -1450,11 +1423,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) *tool_id_ptr = TOOL_ID_NONE; m_tablet_pen_mode = GHOST_kTabletModeNone; - -// ct.Active = GHOST_kTabletModeNone; -// ct.Pressure = 0; -// ct.Xtilt = 0; -// ct.Ytilt = 0; } return GHOST_kSuccess; @@ -1485,16 +1453,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) return GHOST_kFailure; } -/* - // don't involve the window! - GHOST_TabletData& ct = window->GetCocoaTabletData(); - - ct.Pressure = [event pressure]; - NSPoint tilt = [event tilt]; - ct.Xtilt = tilt.x; - ct.Ytilt = tilt.y; -*/ - switch ([event type]) { case NSLeftMouseDown: @@ -1814,12 +1772,9 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const GHOST_TUns8 * temp_buff; size_t pastedTextSize; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard == nil) { - [pool drain]; return NULL; } @@ -1830,14 +1785,12 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const availableTypeFromArray:supportedTypes]; if (bestType == nil) { - [pool drain]; return NULL; } NSString * textPasted = [pasteBoard stringForType:NSStringPboardType]; if (textPasted == nil) { - [pool drain]; return NULL; } @@ -1846,7 +1799,6 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); if (temp_buff == NULL) { - [pool drain]; return NULL; } @@ -1854,8 +1806,6 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const temp_buff[pastedTextSize] = '\0'; - [pool drain]; - if(temp_buff) { return temp_buff; } else { @@ -1869,12 +1819,9 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const if(selection) {return;} // for copying the selection, used on X11 - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard == nil) { - [pool drain]; return; } @@ -1885,8 +1832,6 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const textToCopy = [NSString stringWithCString:buffer encoding:NSISOLatin1StringEncoding]; [pasteBoard setString:textToCopy forType:NSStringPboardType]; - - [pool drain]; } #pragma mark Base directories retrieval @@ -1894,7 +1839,6 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const { static GHOST_TUns8 tempPath[512] = ""; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; NSArray *paths; @@ -1903,20 +1847,17 @@ const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const if ([paths count] > 0) basePath = [paths objectAtIndex:0]; else { - [pool drain]; return NULL; } strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - [pool drain]; return tempPath; } const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const { static GHOST_TUns8 tempPath[512] = ""; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; NSArray *paths; @@ -1925,31 +1866,26 @@ const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const if ([paths count] > 0) basePath = [paths objectAtIndex:0]; else { - [pool drain]; return NULL; } strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - [pool drain]; return tempPath; } const GHOST_TUns8* GHOST_SystemCocoa::getBinaryDir() const { static GHOST_TUns8 tempPath[512] = ""; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; basePath = [[NSBundle mainBundle] bundlePath]; if (basePath == nil) { - [pool drain]; return NULL; } strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - [pool drain]; return tempPath; } diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index c8285547e99..82955e2ce63 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -25,6 +25,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ + /** * @file GHOST_WindowCocoa.h * Declaration of GHOST_WindowCocoa class. @@ -34,13 +35,14 @@ #define _GHOST_WINDOW_COCOA_H_ #ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ + #error Apple OSX only! +#endif #include "GHOST_Window.h" #include "STR_String.h" @class CocoaWindow; +@class NSAutoreleasePool; class GHOST_SystemCocoa; @@ -52,8 +54,8 @@ class GHOST_SystemCocoa; * which is called the gutter. * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent * OpenGL drawing outside the reduced client rectangle. - * @author Maarten Gribnau - * @date May 23, 2001 + * @author Maarten Gribnau + * @date May 23, 2001 */ class GHOST_WindowCocoa : public GHOST_Window { public: @@ -61,16 +63,16 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param systemCocoa The associated system class to forward events to - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) + * @param systemCocoa The associated system class to forward events to + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowCocoa( GHOST_SystemCocoa *systemCocoa, @@ -89,121 +91,121 @@ public: * Destructor. * Closes the window and disposes resources allocated. */ - virtual ~GHOST_WindowCocoa(); + ~GHOST_WindowCocoa(); /** * Returns indication as to whether the window is valid. * @return The validity of the window. */ - virtual bool getValid() const; + bool getValid() const; /** * Returns the associated NSWindow object * @return The associated NSWindow object */ - virtual void* getOSWindow() const; + void* getOSWindow() const; /** * Sets the title displayed in the title bar. * @param title The title to display in the title bar. */ - virtual void setTitle(const STR_String& title); + void setTitle(const STR_String& title); /** * Returns the title displayed in the title bar. * @param title The title displayed in the title bar. */ - virtual void getTitle(STR_String& title) const; + void getTitle(STR_String& title) const; /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. * @param bounds The bounding rectangle of the window. */ - virtual void getWindowBounds(GHOST_Rect& bounds) const; - + void getWindowBounds(GHOST_Rect& bounds) const; + /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. * @param bounds The bounding rectangle of the cleient area of the window. */ - virtual void getClientBounds(GHOST_Rect& bounds) const; + void getClientBounds(GHOST_Rect& bounds) const; /** * Resizes client rectangle width. * @param width The new width of the client area of the window. */ - virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. * @param height The new height of the client area of the window. */ - virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. + * @param width The new width of the client area of the window. + * @param height The new height of the client area of the window. */ - virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); /** * Returns the state of the window (normal, minimized, maximized). * @return The state of the window. */ - virtual GHOST_TWindowState getState() const; + GHOST_TWindowState getState() const; /** * Sets the window "modified" status, indicating unsaved changes * @param isUnsavedChanges Unsaved changes or not * @return Indication of success. */ - virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); - + GHOST_TSuccess setModifiedState(bool isUnsavedChanges); + /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. + * @param inX The x-coordinate on the screen. + * @param inY The y-coordinate on the screen. + * @param outX The x-coordinate in the client rectangle. + * @param outY The y-coordinate in the client rectangle. */ - virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * @param inX The x-coordinate in the client rectangle. + * @param inY The y-coordinate in the client rectangle. + * @param outX The x-coordinate on the screen. + * @param outY The y-coordinate on the screen. */ - virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Gets the screen the window is displayed in * @return The NSScreen object */ NSScreen* getScreen(); - + /** * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. + * @param state The state of the window. + * @return Indication of success. */ - virtual GHOST_TSuccess setState(GHOST_TWindowState state); + GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. + * @param order The order of the window. + * @return Indication of success. */ - virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); + GHOST_TSuccess setOrder(GHOST_TWindowOrder order); /** * Swaps front and back buffers of a window. - * @return A boolean success indicator. + * @return A boolean success indicator. */ - virtual GHOST_TSuccess swapBuffers(); + GHOST_TSuccess swapBuffers(); /** * Updates the drawing context of this window. Needed @@ -216,87 +218,84 @@ public: * Activates the drawing context of this window. * @return A boolean success indicator. */ - virtual GHOST_TSuccess activateDrawingContext(); + GHOST_TSuccess activateDrawingContext(); - virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; - - - const GHOST_TabletData* GetTabletData() - { return NULL; } + void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; /** * Sets the progress bar value displayed in the window/application icon - * @param progress The progress % (0.0 to 1.0) + * @param progress The progress % (0.0 to 1.0) */ - virtual GHOST_TSuccess setProgressBar(float progress); - + GHOST_TSuccess setProgressBar(float progress); + /** * Hides the progress bar icon */ - virtual GHOST_TSuccess endProgressBar(); + GHOST_TSuccess endProgressBar(); + protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. */ - virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); + GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * @return Indication as to whether removal has succeeded. */ - virtual GHOST_TSuccess removeDrawingContext(); + GHOST_TSuccess removeDrawingContext(); /** * Invalidates the contents of this window. - * @return Indication of success. + * @return Indication of success. */ - virtual GHOST_TSuccess invalidate(); + GHOST_TSuccess invalidate(); /** * Sets the cursor visibility on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorVisibility(bool visible); - + GHOST_TSuccess setWindowCursorVisibility(bool visible); + /** * Sets the cursor grab on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode); - + GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode); + /** * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); + GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); /** * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color); - - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); + GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, + int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color); + + GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); - /** The window containing the OpenGL view */ - CocoaWindow *m_window; - - /** The openGL view */ + /** The window containing the OpenGL view */ + CocoaWindow *m_window; + + /** The OpenGL view */ NSOpenGLView *m_openGLView; - /** The opgnGL drawing context */ + /** The OpenGL drawing context */ NSOpenGLContext *m_openGLContext; - - /** The mother SystemCocoa class to send events */ - GHOST_SystemCocoa *m_systemCocoa; - + /** The first created OpenGL context (for sharing display lists) */ static NSOpenGLContext *s_firstOpenGLcontext; - - NSCursor* m_customCursor; + + /** The mother SystemCocoa class to send events */ + GHOST_SystemCocoa *m_ghostSystem; + + NSCursor* m_customCursor; }; #endif // _GHOST_WINDOW_COCOA_H_ diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index c7ec3b398c8..aea59de51cd 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -21,8 +21,8 @@ * * The Original Code is: all of this file. * - * Contributor(s): Maarten Gribnau 05/2001 - Damien Plisson 10/2009 + * Contributor(s): Maarten Gribnau 05/2001 + Damien Plisson 10/2009 * * ***** END GPL LICENSE BLOCK ***** */ @@ -30,15 +30,11 @@ #include #ifndef MAC_OS_X_VERSION_10_6 -//Use of the SetSystemUIMode function (64bit compatible) -#include + //Use of the SetSystemUIMode function (64bit compatible) + #include #endif #include -/***** Multithreaded opengl code : uncomment for enabling -#include -*/ - #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" @@ -56,17 +52,18 @@ extern "C" { extern void wm_event_do_handlers(bContext *C); extern void wm_event_do_notifiers(bContext *C); extern void wm_draw_update(bContext *C); -};*/ +}*/ + @interface CocoaWindowDelegate : NSObject #ifdef MAC_OS_X_VERSION_10_6 - + #endif { - GHOST_SystemCocoa *systemCocoa; - GHOST_WindowCocoa *associatedWindow; + GHOST_SystemCocoa *ghostSystem; + GHOST_WindowCocoa *ghostWindow; } -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; +- (void)setSystem:(GHOST_SystemCocoa *)sysCocoa ghostWindow:(GHOST_WindowCocoa *)winCocoa; - (void)windowWillClose:(NSNotification *)notification; - (void)windowDidBecomeKey:(NSNotification *)notification; - (void)windowDidResignKey:(NSNotification *)notification; @@ -77,40 +74,40 @@ extern "C" { @end @implementation CocoaWindowDelegate : NSObject -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa +- (void)setSystem:(GHOST_SystemCocoa *)sys ghostWindow:(GHOST_WindowCocoa *)win { - systemCocoa = sysCocoa; - associatedWindow = winCocoa; + ghostSystem = sys; + ghostWindow = win; } - (void)windowWillClose:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowClose, ghostWindow); } - (void)windowDidBecomeKey:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowActivate, ghostWindow); } - (void)windowDidResignKey:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowDeactivate, ghostWindow); } - (void)windowDidExpose:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowUpdate, ghostWindow); } - (void)windowDidMove:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowMove, ghostWindow); } - (void)windowWillMove:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowMove, ghostWindow); } - (void)windowDidResize:(NSNotification *)notification @@ -119,13 +116,13 @@ extern "C" { //if (![[notification object] inLiveResize]) { //Send event only once, at end of resize operation (when user has released mouse button) #endif - systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowSize, ghostWindow); #ifdef MAC_OS_X_VERSION_10_6 //} #endif /* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run - if ([[notification object] inLiveResize]) { - systemCocoa->dispatchEvents(); + if ([[notification object] inLiveResize]) { + ghostSystem->dispatchEvents(); wm_window_timer(ghostC); wm_event_do_handlers(ghostC); wm_event_do_notifiers(ghostC); @@ -138,17 +135,17 @@ extern "C" { //We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events) @interface CocoaWindow: NSWindow { - GHOST_SystemCocoa *systemCocoa; - GHOST_WindowCocoa *associatedWindow; + GHOST_SystemCocoa *ghostSystem; + GHOST_WindowCocoa *ghostWindow; GHOST_TDragnDropTypes m_draggedObjectType; } -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; +- (void)setSystem:(GHOST_SystemCocoa *)sys ghostWindow:(GHOST_WindowCocoa *)win; @end @implementation CocoaWindow -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa +- (void)setSystem:(GHOST_SystemCocoa *)sys ghostWindow:(GHOST_WindowCocoa *)win { - systemCocoa = sysCocoa; - associatedWindow = winCocoa; + ghostSystem = sys; + ghostWindow = win; } -(BOOL)canBecomeKeyWindow @@ -162,13 +159,18 @@ extern "C" { NSPoint mouseLocation = [sender draggingLocation]; NSPasteboard *draggingPBoard = [sender draggingPasteboard]; - if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeBitmap; - else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeFilenames; - else if ([[draggingPBoard types] containsObject:NSStringPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeString; - else return NSDragOperationNone; + if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) + m_draggedObjectType = GHOST_kDragnDropTypeBitmap; + else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) + m_draggedObjectType = GHOST_kDragnDropTypeFilenames; + else if ([[draggingPBoard types] containsObject:NSStringPboardType]) + m_draggedObjectType = GHOST_kDragnDropTypeString; + else + return NSDragOperationNone; + + ghostWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, ghostWindow, mouseLocation.x, mouseLocation.y, nil); - associatedWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); return NSDragOperationCopy; } @@ -181,22 +183,19 @@ extern "C" { { NSPoint mouseLocation = [sender draggingLocation]; - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); - return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, ghostWindow, mouseLocation.x, mouseLocation.y, nil); + return ghostWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; } - (void)draggingExited:(id < NSDraggingInfo >)sender { - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, associatedWindow, 0, 0, nil); + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, ghostWindow, 0, 0, nil); m_draggedObjectType = GHOST_kDragnDropTypeUnknown; } - (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender { - if (associatedWindow->canAcceptDragOperation()) - return YES; - else - return NO; + return ghostWindow->canAcceptDragOperation(); } - (BOOL)performDragOperation:(id < NSDraggingInfo >)sender @@ -224,7 +223,7 @@ extern "C" { return NO; break; } - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, (void*)data); + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, ghostWindow, mouseLocation.x, mouseLocation.y, (void*)data); return YES; } @@ -234,11 +233,11 @@ extern "C" { #pragma mark NSOpenGLView subclass //We need to subclass it in order to give Cocoa the feeling key events are trapped -@interface CocoaOpenGLView : NSOpenGLView +@interface BlenderGLView : NSOpenGLView { } @end -@implementation CocoaOpenGLView +@implementation BlenderGLView - (BOOL)acceptsFirstResponder { @@ -288,7 +287,7 @@ extern "C" { NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil; GHOST_WindowCocoa::GHOST_WindowCocoa( - GHOST_SystemCocoa *systemCocoa, + GHOST_SystemCocoa *ghostSystem, const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, @@ -297,48 +296,43 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, const GHOST_TUns16 numOfAASamples -) : - GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples), - m_customCursor(0) + ) + : GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples) + , m_ghostSystem(ghostSystem) + , m_customCursor(0) { - NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40]; - NSOpenGLPixelFormat *pixelFormat = nil; - int i; +// m_pool = [[NSAutoreleasePool alloc] init]; - m_systemCocoa = systemCocoa; m_fullScreen = false; + NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[20]; + NSOpenGLPixelFormat *pixelFormat = nil; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //Creates the window - NSRect rect; - NSSize minSize; - - rect.origin.x = left; - rect.origin.y = top; - rect.size.width = width; - rect.size.height = height; + NSRect rect = NSMakeRect(left,top,width,height); m_window = [[CocoaWindow alloc] initWithContentRect:rect - styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask - backing:NSBackingStoreBuffered defer:NO]; + styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask + backing:NSBackingStoreBuffered defer:NO]; if (m_window == nil) { [pool drain]; return; } - [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; + [m_window setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; - //Forbid to resize the window below the blender defined minimum one - minSize.width = 320; - minSize.height = 240; - [m_window setContentMinSize:minSize]; + // Forbid to resize the window below the blender defined minimum one + [m_window setContentMinSize:NSMakeSize(320,240)]; - setTitle(title); + // simplify drawing since each window contains only our OpenGL view + [m_window useOptimizedDrawing:YES]; + setTitle(title); // Pixel Format Attributes for the windowed NSOpenGLContext - i=0; + int i = 0; pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer @@ -346,14 +340,14 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; - //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; - if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; + int firstMultiSampleAttribute = i; + if (numOfAASamples>0) { // Multisample anti-aliasing pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample; @@ -374,25 +368,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( //Fall back to no multisampling if Antialiasing init failed if (pixelFormat == nil) { - i=0; - pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; - - // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer - // needed for 'Draw Overlap' drawing method - pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; - - pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; - //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway - - pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; - pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; - - if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; - - pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; - + pixelFormatAttrsWindow[firstMultiSampleAttribute] = (NSOpenGLPixelFormatAttribute) 0; pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; - } if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value @@ -405,8 +382,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( } //Creates the OpenGL View inside the window - m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect - pixelFormat:pixelFormat]; + m_openGLView = [[BlenderGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; [pixelFormat release]; @@ -424,13 +400,13 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( activateDrawingContext(); CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; - [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; + [windowDelegate setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; [m_window setDelegate:windowDelegate]; [m_window setAcceptsMouseMovedEvents:YES]; - [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, - NSStringPboardType, NSTIFFPboardType, nil]]; + [m_window registerForDraggedTypes:[NSArray arrayWithObjects: + NSFilenamesPboardType, NSStringPboardType, NSTIFFPboardType, nil]]; if (state == GHOST_kWindowStateFullScreen) setState(GHOST_kWindowStateFullScreen); @@ -443,7 +419,7 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() { if (m_customCursor) delete m_customCursor; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView release]; if (m_window) { @@ -458,7 +434,8 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - [pool drain]; + +// [pool drain]; } #pragma mark accessors @@ -479,21 +456,18 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithUTF8String:title]; - + //Set associated file if applicable if ([windowTitle hasPrefix:@"Blender"]) { NSRange fileStrRange; - NSString *associatedFileName; - int len; - + fileStrRange.location = [windowTitle rangeOfString:@"["].location+1; - len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location; - - if (len >0) - { + int len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location; + + if (len >0) { fileStrRange.length = len; - associatedFileName = [windowTitle substringWithRange:fileStrRange]; + NSString* associatedFileName = [windowTitle substringWithRange:fileStrRange]; @try { [m_window setRepresentedFilename:associatedFileName]; } @@ -506,13 +480,11 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) [m_window setTitle:windowTitle]; [m_window setRepresentedFilename:@""]; } - } else { [m_window setTitle:windowTitle]; [m_window setRepresentedFilename:@""]; } - [windowTitle release]; [pool drain]; } @@ -520,16 +492,20 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) void GHOST_WindowCocoa::getTitle(STR_String& title) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +/* NSString *windowTitle = [m_window title]; if (windowTitle != nil) { title = [windowTitle UTF8String]; } - +*/ + + title = [[m_window title] UTF8String]; + [pool drain]; } @@ -539,8 +515,6 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const NSRect rect; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSRect screenSize = [[m_window screen] visibleFrame]; rect = [m_window frame]; @@ -549,28 +523,23 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const bounds.m_l = rect.origin.x -screenSize.origin.x; bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width; bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y); - - [pool drain]; } void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const { - NSRect rect; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid") - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + if (!m_fullScreen) { NSRect screenSize = [[m_window screen] visibleFrame]; //Max window contents as screen size (excluding title bar...) NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize - styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)]; + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)]; + + NSRect rect = [m_window contentRectForFrameRect:[m_window frame]]; - rect = [m_window contentRectForFrameRect:[m_window frame]]; - bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y); bounds.m_l = rect.origin.x -contentRect.origin.x; bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width; @@ -578,20 +547,19 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const } else { NSRect screenSize = [[m_window screen] frame]; - + bounds.m_b = screenSize.origin.y + screenSize.size.height; bounds.m_l = screenSize.origin.x; bounds.m_r = screenSize.origin.x + screenSize.size.width; bounds.m_t = screenSize.origin.y; } - [pool drain]; } GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if (((GHOST_TUns32)cBnds.getWidth()) != width) { @@ -600,7 +568,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) size.height=cBnds.getHeight(); [m_window setContentSize:size]; } - [pool drain]; + return GHOST_kSuccess; } @@ -608,7 +576,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if (((GHOST_TUns32)cBnds.getHeight()) != height) { @@ -617,7 +585,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) size.height=height; [m_window setContentSize:size]; } - [pool drain]; + return GHOST_kSuccess; } @@ -625,7 +593,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if ((((GHOST_TUns32)cBnds.getWidth()) != width) || @@ -635,7 +603,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 size.height=height; [m_window setContentSize:size]; } - [pool drain]; + return GHOST_kSuccess; } @@ -665,15 +633,11 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid") - - NSPoint screenCoord; - NSPoint baseCoord; - - screenCoord.x = inX; - screenCoord.y = inY; - - baseCoord = [m_window convertScreenToBase:screenCoord]; - + + NSPoint screenCoord = {inX, inY}; + + NSPoint baseCoord = [m_window convertScreenToBase:screenCoord]; + outX = baseCoord.x; outY = baseCoord.y; } @@ -682,15 +646,11 @@ void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid") - - NSPoint screenCoord; - NSPoint baseCoord; - - baseCoord.x = inX; - baseCoord.y = inY; - - screenCoord = [m_window convertBaseToScreen:baseCoord]; - + + NSPoint baseCoord = {inX, inY}; + + NSPoint screenCoord = [m_window convertBaseToScreen:baseCoord]; + outX = screenCoord.x; outY = screenCoord.y; } @@ -710,19 +670,18 @@ NSScreen* GHOST_WindowCocoa::getScreen() GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid") - switch (state) { + switch (state) { case GHOST_kWindowStateMinimized: - [m_window miniaturize:nil]; - break; + [m_window miniaturize:nil]; + break; case GHOST_kWindowStateMaximized: [m_window zoom:nil]; break; - case GHOST_kWindowStateFullScreen: if (!m_fullScreen) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + //This status change needs to be done before Cocoa call to enter fullscreen mode //to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference m_fullScreen = true; @@ -759,10 +718,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [tmpWindow setReleasedWhenClosed:NO]; [tmpWindow setAcceptsMouseMovedEvents:YES]; [tmpWindow setDelegate:[m_window delegate]]; - + //Assign the openGL view to the new window [tmpWindow setContentView:m_openGLView]; - + //Show the new window [tmpWindow makeKeyAndOrderFront:nil]; //Close and release old window @@ -771,10 +730,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [m_window release]; m_window = tmpWindow; #endif - //Tell WM of view new size - m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this); - + m_ghostSystem->handleWindowEvent(GHOST_kEventWindowSize, this); + [pool drain]; } break; @@ -807,20 +765,20 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) } //Create a fullscreen borderless window CocoaWindow *tmpWindow = [[CocoaWindow alloc] - initWithContentRect:[[m_window screen] frame] - styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) - backing:NSBackingStoreBuffered - defer:YES]; + initWithContentRect:[[m_window screen] frame] + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:YES]; //Copy current window parameters [tmpWindow setTitle:[m_window title]]; [tmpWindow setRepresentedFilename:[m_window representedFilename]]; [tmpWindow setReleasedWhenClosed:NO]; [tmpWindow setAcceptsMouseMovedEvents:YES]; [tmpWindow setDelegate:[m_window delegate]]; - + //Assign the openGL view to the new window [tmpWindow setContentView:m_openGLView]; - + //Show the new window [tmpWindow makeKeyAndOrderFront:nil]; //Close and release old window @@ -829,53 +787,51 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [m_window release]; m_window = tmpWindow; #endif - //Tell WM of view new size - m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this); - + m_ghostSystem->handleWindowEvent(GHOST_kEventWindowSize, this); + [pool drain]; } - else if ([m_window isMiniaturized]) + else if ([m_window isMiniaturized]) [m_window deminiaturize:nil]; else if ([m_window isZoomed]) [m_window zoom:nil]; - break; - } - return GHOST_kSuccess; + break; + } + return GHOST_kSuccess; } GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + [m_window setDocumentEdited:isUnsavedChanges]; - + [pool drain]; + return GHOST_Window::setModifiedState(isUnsavedChanges); } GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid") - if (order == GHOST_kWindowOrderTop) { + if (order == GHOST_kWindowOrderTop) { [m_window makeKeyAndOrderFront:nil]; - } - else { - NSArray *windowsList; - + } + else { [m_window orderBack:nil]; - + //Check for other blender opened windows and make the frontmost key - windowsList = [NSApp orderedWindows]; + NSArray* windowsList = [NSApp orderedWindows]; if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - } - + } + [pool drain]; - return GHOST_kSuccess; + return GHOST_kSuccess; } #pragma mark Drawing context @@ -884,15 +840,19 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_TSuccess GHOST_WindowCocoa::swapBuffers() { - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_openGLContext != nil) { + GHOST_TSuccess success = GHOST_kFailure; + + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_openGLContext != nil) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext flushBuffer]; [pool drain]; - return GHOST_kSuccess; - } - } - return GHOST_kFailure; + success = GHOST_kSuccess; + } + } + +// [m_pool drain]; // needed to put this in a function that is called regularly + return success; } GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext() @@ -912,12 +872,12 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() { if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { if (m_openGLContext != nil) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext makeCurrentContext]; - + // Disable AA by default if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB); - [pool drain]; +// [pool drain]; return GHOST_kSuccess; } } @@ -928,35 +888,34 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type) { GHOST_TSuccess success = GHOST_kFailure; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSOpenGLPixelFormat *pixelFormat; NSOpenGLContext *tmpOpenGLContext; - + /***** Multithreaded opengl code : uncomment for enabling CGLContextObj cglCtx; */ - + switch (type) { case GHOST_kDrawingContextTypeOpenGL: if (!getValid()) break; - + pixelFormat = [m_openGLView pixelFormat]; tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat - shareContext:s_firstOpenGLcontext]; + shareContext:s_firstOpenGLcontext]; if (tmpOpenGLContext == nil) { success = GHOST_kFailure; break; } - + //Switch openGL to multhreaded mode - /******* Multithreaded opengl code : uncomment for enabling + /******* Multithreaded opengl code : uncomment for enabling */ cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj]; if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError) printf("\nSwitched openGL to multithreaded mode"); - */ - + if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext; #ifdef WAIT_FOR_VSYNC { @@ -967,25 +926,25 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp #endif [m_openGLView setOpenGLContext:tmpOpenGLContext]; [tmpOpenGLContext setView:m_openGLView]; - + m_openGLContext = tmpOpenGLContext; break; - + case GHOST_kDrawingContextTypeNone: success = GHOST_kSuccess; break; - + default: break; } - [pool drain]; +// [pool drain]; return success; } GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; switch (m_drawingContextType) { case GHOST_kDrawingContextTypeOpenGL: if (m_openGLContext) @@ -994,14 +953,14 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil; m_openGLContext = nil; } - [pool drain]; +// [pool drain]; return GHOST_kSuccess; case GHOST_kDrawingContextTypeNone: - [pool drain]; +// [pool drain]; return GHOST_kSuccess; break; default: - [pool drain]; +// [pool drain]; return GHOST_kFailure; } } @@ -1010,9 +969,9 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() GHOST_TSuccess GHOST_WindowCocoa::invalidate() { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView setNeedsDisplay:YES]; - [pool drain]; +// [pool drain]; return GHOST_kSuccess; } @@ -1021,36 +980,36 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate() GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + if ((progress >=0.0) && (progress <=1.0)) { NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; - + [dockIcon lockFocus]; - NSRect progressBox = {{4, 4}, {120, 16}}; - - [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; - - // Track & Outline - [[NSColor blackColor] setFill]; - NSRectFill(progressBox); - - [[NSColor whiteColor] set]; - NSFrameRect(progressBox); - - // Progress fill - progressBox = NSInsetRect(progressBox, 1, 1); - [[NSColor knobColor] setFill]; - progressBox.size.width = progressBox.size.width * progress; + NSRect progressBox = {{4, 4}, {120, 16}}; + + [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; + + // Track & Outline + [[NSColor blackColor] setFill]; NSRectFill(progressBox); - + + [[NSColor whiteColor] set]; + NSFrameRect(progressBox); + + // Progress fill + progressBox = NSInsetRect(progressBox, 1, 1); + [[NSColor knobColor] setFill]; + progressBox.size.width = progressBox.size.width * progress; + NSRectFill(progressBox); + [dockIcon unlockFocus]; - + [NSApp setApplicationIconImage:dockIcon]; [dockIcon release]; - + m_progressBarVisible = true; } - + [pool drain]; return GHOST_kSuccess; } @@ -1060,16 +1019,16 @@ GHOST_TSuccess GHOST_WindowCocoa::endProgressBar() { if (!m_progressBarVisible) return GHOST_kFailure; m_progressBarVisible = false; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; [dockIcon lockFocus]; [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; [dockIcon unlockFocus]; [NSApp setApplicationIconImage:dockIcon]; [dockIcon release]; - + [pool drain]; return GHOST_kSuccess; } @@ -1081,9 +1040,9 @@ GHOST_TSuccess GHOST_WindowCocoa::endProgressBar() void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const { static bool systemCursorVisible = true; - + NSCursor *tmpCursor =nil; - + if (visible != systemCursorVisible) { if (visible) { [NSCursor unhide]; @@ -1126,6 +1085,7 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c case GHOST_kStandardCursorRightSide: tmpCursor = [NSCursor resizeRightCursor]; break; +#if 0 // illustrative code -- no need to compile case GHOST_kStandardCursorRightArrow: case GHOST_kStandardCursorInfo: case GHOST_kStandardCursorLeftArrow: @@ -1139,10 +1099,11 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c case GHOST_kStandardCursorBottomLeftCorner: case GHOST_kStandardCursorCopy: case GHOST_kStandardCursorDefault: +#endif default: tmpCursor = [NSCursor arrowCursor]; break; - }; + } } [tmpCursor set]; } @@ -1151,13 +1112,10 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - if ([m_window isVisible]) { loadCursor(visible, getCursorShape()); } - - [pool drain]; + return GHOST_kSuccess; } @@ -1165,30 +1123,27 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode) { GHOST_TSuccess err = GHOST_kSuccess; - + if (mode != GHOST_kGrabDisable) { //No need to perform grab without warp as it is always on in OS X if(mode != GHOST_kGrabNormal) { GHOST_TInt32 x_old,y_old; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - m_systemCocoa->getCursorPosition(x_old,y_old); + m_ghostSystem->getCursorPosition(x_old,y_old); screenToClient(x_old, y_old, m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]); //Warp position is stored in client (window base) coordinates setCursorGrabAccum(0, 0); - + if(mode == GHOST_kGrabHide) { setWindowCursorVisibility(false); } - + //Make window key if it wasn't to get the mouse move events [m_window makeKeyWindow]; - + //Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure; - - [pool drain]; } } else { @@ -1197,7 +1152,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode //No need to set again cursor position, as it has not changed for Cocoa setWindowCursorVisibility(true); } - + err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure; /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */ setCursorGrabAccum(0, 0); @@ -1205,11 +1160,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode } return err; } - + GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (m_customCursor) { [m_customCursor release]; m_customCursor = nil; @@ -1218,8 +1171,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor sha if ([m_window isVisible]) { loadCursor(getCursorVisibility(), shape); } - - [pool drain]; + return GHOST_kSuccess; } @@ -1245,7 +1197,7 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) } GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) + int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) { int y,nbUns16; NSPoint hotSpotPoint; @@ -1253,31 +1205,29 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap NSImage *cursorImage; NSSize imSize; GHOST_TUns16 *cursorBitmap; - - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + if (m_customCursor) { [m_customCursor release]; m_customCursor = nil; } - - - cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil - pixelsWide:sizex - pixelsHigh:sizey - bitsPerSample:1 - samplesPerPixel:2 - hasAlpha:YES - isPlanar:YES - colorSpaceName:NSDeviceWhiteColorSpace - bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0)) - bitsPerPixel:1]; - - + + cursorImageRep = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:nil + pixelsWide:sizex + pixelsHigh:sizey + bitsPerSample:1 + samplesPerPixel:2 + hasAlpha:YES + isPlanar:YES + colorSpaceName:NSDeviceWhiteColorSpace + bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0)) + bitsPerPixel:1]; + cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData]; nbUns16 = [cursorImageRep bytesPerPlane]/2; - + for (y=0; y Date: Fri, 17 Dec 2010 00:13:23 +0000 Subject: late summer -- overhauled tablet-handling for Windows --- intern/ghost/intern/GHOST_SystemWin32.cpp | 2 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 671 ++++++++++------------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 68 +-- 3 files changed, 326 insertions(+), 415 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 0315fa5870a..cc0e0cb2bec 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1022,7 +1022,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM { // tablet manager handles all its own cursor moves. // ignore 'regular' mouse while a tablet tool is being used. - DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam); + // DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam); eventHandled = true; break; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 868b5dcc162..0b2e49fbacc 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -10,13 +10,29 @@ #include #include -#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION) -#define PACKETMODE (0 /*PK_BUTTONS*/) -// #define PACKETTILT PKEXT_ABSOLUTE +#define MAX_QUEUE_SIZE 100 -#include "pktdef.h" +static bool wintab_initialized = false; -#define MAX_QUEUE_SIZE 100 +// BEGIN from Wacom's Utils.h +typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); +typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); +typedef BOOL ( API * WTCLOSE ) ( HCTX ); +typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); +typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); +typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); +// END + +// the Wintab library +static HMODULE lib_Wintab; + +// WinTab function pointers +static WTOPENA func_Open; +static WTCLOSE func_Close; +static WTINFOA func_Info; +static WTQUEUESIZESET func_QueueSizeSet; +static WTPACKETSGET func_PacketsGet; +static WTPACKET func_Packet; static void print(AXIS const& t, char const* label = NULL) { @@ -54,121 +70,225 @@ static void print(WTPKT packet) } } -GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() - : activeWindow(NULL) +Tablet::Tablet(int tabletID) + : id(tabletID) { - dropTool(); + GHOST_ASSERT(wintab_initialized, "Tablet objects should only be created by TabletManager"); + + // query for overall capabilities and ranges + func_Info(WTI_DEVICES, DVC_NAME, name); + printf("\n-- tablet %d: %s --\n", id, name); + + puts("\nactive tablet area"); + AXIS xRange, yRange; + func_Info(WTI_DEVICES + id, DVC_X, &xRange); + func_Info(WTI_DEVICES + id, DVC_Y, &yRange); + print(xRange,"x"); print(yRange,"y"); + size_x = xRange.axMax; + size_y = yRange.axMax; + + func_Info(WTI_DEVICES + id, DVC_NCSRTYPES, &cursorCount); + func_Info(WTI_DEVICES + id, DVC_FIRSTCSR, &cursorBase); + printf("\nowns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1); + + func_Info(WTI_DEVICES + id, DVC_PKTDATA, &(allTools)); + puts("\nall tools have"); print(allTools); + func_Info(WTI_DEVICES + id, DVC_CSRDATA, &(someTools)); + puts("some tools also have"); print(someTools); + + puts("\npressure sensitivity"); + AXIS pressureRange; + hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE + && func_Info(WTI_DEVICES + id, DVC_NPRESSURE, &pressureRange) + && pressureRange.axMax; + + if (hasPressure) + { + print(pressureRange); + pressureScale = 1.f / pressureRange.axMax; + } + else + pressureScale = 0.f; - // open WinTab - lib_Wintab = LoadLibrary("wintab32.dll"); + puts("\ntilt sensitivity"); + AXIS tiltRange[3]; + hasTilt = (allTools|someTools) & PK_ORIENTATION + && func_Info(WTI_DEVICES + id, DVC_ORIENTATION, tiltRange) + && tiltRange[0].axResolution && tiltRange[1].axResolution; - if (lib_Wintab) + if (hasTilt) { - // connect function pointers - func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA"); - func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose"); - func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); - func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); - func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); - func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); + // leave this code in place to help support tablets I haven't tested + const char* axisName[] = {"azimuth","altitude","twist"}; + for (int i = 0; i < 3; ++i) + print(tiltRange[i], axisName[i]); - puts("\n-- essential tablet info --"); - func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); - func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); + azimuthScale = 1.f / tiltRange[0].axMax; + altitudeScale = 1.f / tiltRange[1].axMax; + } + else + { + puts("none"); + azimuthScale = altitudeScale = 0.f; + } - func_Info(WTI_DEVICES, DVC_PKTDATA, &allTools); - puts("\nall tools have"); print(allTools); - func_Info(WTI_DEVICES, DVC_CSRDATA, &someTools); - puts("some tools also have"); print(someTools); + for (UINT i = cursorBase; i < cursorBase + cursorCount; ++i) + { + // what can each cursor do? - puts("\npressure sensitivity"); - AXIS pressureRange; - hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE - && func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange); + UINT physID; + func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID); + if (physID == 0) + // each 'real' cursor has a physical ID + // (on Wacom at least, not tested with other vendors) + continue; - if (hasPressure) - { - print(pressureRange); - pressureScale = 1.f / pressureRange.axMax; - } - else - pressureScale = 0.f; + TCHAR name[40]; + func_Info(WTI_CURSORS + i, CSR_NAME, name); + printf("\ncursor %d: %s\n", i, name); - puts("\ntilt sensitivity"); - AXIS tiltRange[3]; - hasTilt = (allTools|someTools) & PK_ORIENTATION - && func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange); + // always returns 'yes' so don't bother + // BOOL active; + // func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active); + // printf("active: %s\n", active ? "yes" : "no"); - if (hasTilt) - { - // leave this code in place to help support tablets I haven't tested - const char* axisName[] = {"azimuth","altitude","twist"}; - for (int i = 0; i < 3; ++i) - print(tiltRange[i], axisName[i]); - - // cheat by using available data from Intuos4. test on other tablets!!! - azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); - altitudeScale = 1.f / tiltRange[1].axMax; - } - else + WTPKT packet; + func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(packet & someTools); + + puts("buttons:"); + BYTE buttons; + BYTE sysButtonMap[32]; + func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons); + func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap); + for (int i = 0; i < buttons; ++i) + printf(" %d -> %d\n", i, sysButtonMap[i]); + } + } + +bool Tablet::ownsCursor(int cursor) + { + return (cursor - cursorBase) < cursorCount; + } + +TabletTool Tablet::toolForCursor(int cursor) + { + TabletTool tool = {TABLET_NONE,false,false}; + if (ownsCursor(cursor)) + { + // try one way to classify cursor + UINT cursorType = (cursor - cursorBase) % cursorCount; + printf("%d mod %d = %d\n", cursor - cursorBase, cursorCount, cursorType); + switch (cursorType) { - puts("none"); - azimuthScale = altitudeScale = 0.f; + case 0: // older Intuos tablets can track two cursors at once + case 3: // so we test for both here + tool.type = TABLET_MOUSE; + break; + case 1: + case 4: + tool.type = TABLET_PEN; + break; + case 2: + case 5: + tool.type = TABLET_ERASER; + break; + default: + tool.type = TABLET_NONE; } -#if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed - // this isn't working for [mce], so let it rest for now - puts("\nraw tilt sensitivity"); - hasTilt = false; - UINT tag = 0; - UINT extensionCount; - func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); - for (UINT i = 0; i < extensionCount; ++i) + #if 0 + // now try another way + func_Info(WTI_CURSORS + cursor, CSR_TYPE, &cursorType); + switch (cursorType & 0xf06) { - printf("trying extension %d\n", i); - func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); - if (tag == WTX_TILT) - { - hasTilt = true; + case 0x802: + puts("general stylus"); break; - } + case 0x902: + puts("airbrush"); + break; + case 0x804: + puts("art pen"); + break; + case 0x004: + puts("4D mouse"); + break; + case 0x006: + puts("5-button puck"); + break; + default: + puts("???"); } + #endif - if (hasTilt) + WTPKT toolData; + func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData); + // discard any stray capabilities + // (sometimes cursors claim to be able to do things + // that their tablet doesn't support) + toolData &= (allTools|someTools); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(toolData & someTools); + putchar('\n'); + + if (tool.type == TABLET_MOUSE) { - AXIS tiltRange[2]; - func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange); - print("x", tiltRange[0]); - print("y", tiltRange[1]); - tiltScaleX = 1.f / tiltRange[0].axMax; - tiltScaleY = 1.f / tiltRange[1].axMax; - func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); + // don't always trust CSR_PKTDATA! + tool.hasPressure = false; + tool.hasTilt = false; } else { - puts("none"); - tiltScaleX = tiltScaleY = 0.f; + tool.hasPressure = toolData & PK_NORMAL_PRESSURE; + tool.hasTilt = toolData & PK_ORIENTATION; } -#endif // WTX_TILT + } + + return tool; + } + +GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() + : activeWindow(NULL) + { + dropTool(); + + // open WinTab + GHOST_ASSERT(!wintab_initialized,"There should be only one TabletManagerWin32 object"); + lib_Wintab = LoadLibrary("wintab32.dll"); + + if (lib_Wintab) + { + // connect function pointers + func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA"); + func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose"); + func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); + func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); + func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); + func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); + + wintab_initialized = true; - getExtraInfo(); + getHardwareInfo(); } } GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32() { // close WinTab + wintab_initialized = false; FreeLibrary(lib_Wintab); } -void GHOST_TabletManagerWin32::getExtraInfo() +void GHOST_TabletManagerWin32::getHardwareInfo() { - puts("\n-- extra tablet info --"); + puts("\n-- graphics tablet info --"); WORD specV, implV; func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); - printf("WinTab version %d.%d (%d.%d)\n", + printf("WinTab version %d.%d (%d.%d)\n\n", HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); UINT extensionCount; @@ -183,113 +303,17 @@ void GHOST_TabletManagerWin32::getExtraInfo() UINT deviceCount, cursorCount; func_Info(WTI_INTERFACE, IFC_NDEVICES, &deviceCount); func_Info(WTI_INTERFACE, IFC_NCURSORS, &cursorCount); + printf("\n%d tablets, %d tools\n", deviceCount, cursorCount); - printf("%d tablets, %d tools\n", deviceCount, cursorCount); if (deviceCount > 1) ; // support this? for (UINT i = 0; i < deviceCount; ++i) { - Tablet tablet; - - // query for overall capabilities and ranges - char tabletName[LC_NAMELEN]; - if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) - printf("tablet %d: %s\n", i, tabletName); - - puts("\nactive tablet area"); - AXIS xRange, yRange; - func_Info(WTI_DEVICES + i, DVC_X, &xRange); - func_Info(WTI_DEVICES + i, DVC_Y, &yRange); - tablet.size_x = xRange.axMax; - tablet.size_y = yRange.axMax; - print(xRange,"x"); print(yRange,"y"); - - func_Info(WTI_DEVICES + i, DVC_NCSRTYPES, &cursorCount); - func_Info(WTI_DEVICES + i, DVC_FIRSTCSR, &cursorBase); - tablet.cursorBase = cursorBase; - tablet.cursorCount = cursorCount; - printf("owns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1); - - func_Info(WTI_DEVICES + i, DVC_PKTDATA, &allTools); - puts("\nall tools have"); print(allTools); - func_Info(WTI_DEVICES + i, DVC_CSRDATA, &someTools); - puts("some tools also have"); print(someTools); - - puts("\npressure sensitivity"); - AXIS pressureRange; - hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE - && func_Info(WTI_DEVICES + i, DVC_NPRESSURE, &pressureRange); - - if (hasPressure) - { - print(pressureRange); - pressureScale = 1.f / pressureRange.axMax; - } - else - pressureScale = 0.f; - - puts("\ntilt sensitivity"); - AXIS tiltRange[3]; - hasTilt = (allTools|someTools) & PK_ORIENTATION - && func_Info(WTI_DEVICES + i, DVC_ORIENTATION, &tiltRange); - - if (hasTilt) - { - // leave this code in place to help support tablets I haven't tested - const char* axisName[] = {"azimuth","altitude","twist"}; - for (int i = 0; i < 3; ++i) - print(tiltRange[i], axisName[i]); - - // cheat by using available data from Intuos4. test on other tablets!!! - // azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); - // altitudeScale = 1.f / tiltRange[1].axMax; - - azimuthScale = 1.f / tiltRange[0].axMax; - altitudeScale = 1.f / tiltRange[1].axMax; - } - else - { - puts("none"); - azimuthScale = altitudeScale = 0.f; - } - + Tablet tablet(i); tablets.push_back(tablet); } - for (UINT i = 0; i < cursorCount; ++i) - { - // what can each cursor do? - - UINT physID; - func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID); - if (physID == 0) - // each 'real' cursor has a physical ID - // (on Intuos at least, test on Graphire also) - continue; - - TCHAR name[40]; - func_Info(WTI_CURSORS + i, CSR_NAME, name); - printf("\ncursor %d: %s\n", i, name); - - BOOL active; - func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active); - printf("active: %s\n", active ? "yes" : "no"); - - WTPKT packet; - func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet); - // only report the 'special' bits that distinguish this cursor from the rest - puts("packet support"); print(packet & someTools); - - puts("buttons:"); - BYTE buttons; - BYTE sysButtonMap[32]; - func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons); - func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap); - for (int i = 0; i < buttons; ++i) - printf(" %d -> %d\n", i, sysButtonMap[i]); - } - putchar('\n'); } @@ -314,35 +338,29 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // this window already has a tablet context return; + int id = 0; // for testing... + // set up context LOGCONTEXT archetype; - func_Info(WTI_DEFSYSCTX, 0, &archetype); +// func_Info(WTI_DEFSYSCTX, 0, &archetype); // func_Info(WTI_DEFCONTEXT, 0, &archetype); -// func_Info(WTI_DSCTXS, 0, &archetype); + func_Info(WTI_DSCTXS + id, 0, &archetype); strcpy(archetype.lcName, "blender special"); - WTPKT packetData = PACKETDATA; - if (!hasPressure) - packetData &= ~PK_NORMAL_PRESSURE; - if (!hasTilt) - packetData &= ~PK_ORIENTATION; - archetype.lcPktData = packetData; - + archetype.lcPktData = PACKETDATA; archetype.lcPktMode = PACKETMODE; + archetype.lcMoveMask = PACKETDATA; + // archetype.lcOptions |= CXO_CSRMESSAGES; // <-- lean mean version archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; -#if PACKETMODE & PK_BUTTONS - // we want first 5 buttons - archetype.lcBtnDnMask = 0x1f; - archetype.lcBtnUpMask = 0x1f; -#endif + archetype.lcSysMode = 1; // relative mode (mouse acts like mouse?) // BEGIN derived from Wacom's TILTTEST.C: AXIS TabletX, TabletY; - func_Info(WTI_DEVICES,DVC_X,&TabletX); - func_Info(WTI_DEVICES,DVC_Y,&TabletY); + func_Info(WTI_DEVICES + id,DVC_X,&TabletX); + func_Info(WTI_DEVICES + id,DVC_Y,&TabletY); archetype.lcInOrgX = 0; archetype.lcInOrgY = 0; archetype.lcInExtX = TabletX.axMax; @@ -354,12 +372,6 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); // END -/* if (hasTilt) - { - archetype.lcPktData |= tiltMask; - archetype.lcMoveMask |= tiltMask; - } */ - // open the context HCTX context = func_Open(window->getHWND(), &archetype, TRUE); @@ -387,40 +399,74 @@ void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) } } -void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolData& data) +void Tablet::attachData(PACKET const& packet, TabletToolData& data) { - // this code used to live in GHOST_WindowWin32 - // now it lives here - - float vecLen; - float altRad, azmRad; /* in radians */ - - /* - from the wintab spec: - orAzimuth Specifies the clockwise rotation of the - cursor about the z axis through a full circular range. - - orAltitude Specifies the angle with the x-y plane - through a signed, semicircular range. Positive values - specify an angle upward toward the positive z axis; - negative values specify an angle downward toward the negative z axis. - - wintab.h defines .orAltitude as a UINT but documents .orAltitude - as positive for upward angles and negative for downward angles. - WACOM uses negative altitude values to show that the pen is inverted; - therefore we cast .orAltitude as an (int) and then use the absolute value. - */ - - /* convert raw fixed point data to radians */ - altRad = fabs(ort.orAltitude) * altitudeScale * M_PI/2.0; - azmRad = ort.orAzimuth * azimuthScale * M_PI*2.0; - - /* find length of the stylus' projected vector on the XY plane */ - vecLen = cos(altRad); - - /* from there calculate X and Y components based on azimuth */ - data.tilt_x = sin(azmRad) * vecLen; - data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; + if (data.tool.hasPressure) + { + if (packet.pkNormalPressure) + { + data.pressure = pressureScale * packet.pkNormalPressure; + printf(" %d%%", (int)(100 * data.pressure)); + } + else + data.tool.hasPressure = false; + } + + if (data.tool.hasTilt) + { + ORIENTATION const& o = packet.pkOrientation; + if (o.orAzimuth || o.orAltitude) + { + // this code used to live in GHOST_WindowWin32 + // now it lives here + + float vecLen; + float altRad, azmRad; /* in radians */ + + /* + from the wintab spec: + orAzimuth Specifies the clockwise rotation of the + cursor about the z axis through a full circular range. + + orAltitude Specifies the angle with the x-y plane + through a signed, semicircular range. Positive values + specify an angle upward toward the positive z axis; + negative values specify an angle downward toward the negative z axis. + + wintab.h defines .orAltitude as a UINT but documents .orAltitude + as positive for upward angles and negative for downward angles. + WACOM uses negative altitude values to show that the pen is inverted; + therefore we cast .orAltitude as an (int) and then use the absolute value. + */ + + /* convert raw fixed point data to radians */ + altRad = fabs(o.orAltitude) * altitudeScale * M_PI/2.0; + azmRad = o.orAzimuth * azimuthScale * M_PI*2.0; + + /* find length of the stylus' projected vector on the XY plane */ + vecLen = cos(altRad); + + /* from there calculate X and Y components based on azimuth */ + data.tilt_x = sin(azmRad) * vecLen; + data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; + + if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) + { + // really should fix the initial test for tool.hasTilt, + // not apply a band-aid here. + data.tool.hasTilt = false; + data.tilt_x = 0.f; + data.tilt_y = 0.f; + } + else + { + // printf(" /%d,%d/", o.orAzimuth, o.orAltitude); + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + } + } + else + data.tool.hasTilt = false; + } } bool GHOST_TabletManagerWin32::convertButton(const UINT button, GHOST_TButtonMask& ghost) @@ -466,16 +512,17 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { PACKET const& packet = packets[i]; TabletToolData data = {activeTool}; + int x = packet.pkX; int y = packet.pkY; if (activeTool.type == TABLET_MOUSE) { // until scaling is working better, use system cursor position instead - POINT systemPos; - GetCursorPos(&systemPos); - x = systemPos.x; - y = systemPos.y; +// POINT systemPos; +// GetCursorPos(&systemPos); +// x = systemPos.x; +// y = systemPos.y; if (x == prevMouseX && y == prevMouseY && packet.pkButtons == prevButtons) // don't send any "mouse hasn't moved" events @@ -509,73 +556,14 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) printf(" (%d,%d)", x, y); - if (activeTool.hasPressure) - { - if (packet.pkNormalPressure) - { - data.pressure = pressureScale * packet.pkNormalPressure; - printf(" %d%%", (int)(100 * data.pressure)); - } - else - data.tool.hasPressure = false; - } - - if (activeTool.hasTilt) - { - ORIENTATION const& o = packet.pkOrientation; - - if (o.orAzimuth || o.orAltitude) - { - convertTilt(o, data); - if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) - { - // really should fix the initial test for activeTool.hasTilt, - // not apply a band-aid here. - data.tool.hasTilt = false; - data.tilt_x = 0.f; - data.tilt_y = 0.f; - } - else - { - // printf(" /%d,%d/", o.orAzimuth, o.orAltitude); - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); - } - } - else - data.tool.hasTilt = false; - // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; - // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; - } + activeTablet->attachData(packet, data); // at this point, construct a GHOST event and push it into the queue! GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); // any buttons changed? - #if PACKETMODE & PK_BUTTONS // relative buttons mode - if (packet.pkButtons) - { - // which button? - GHOST_TButtonMask e_button; - int buttonNumber = LOWORD(packet.pkButtons); - e_button = (GHOST_TButtonMask) buttonNumber; - - // pressed or released? - GHOST_TEventType e_action; - int buttonAction = HIWORD(packet.pkButtons); - if (buttonAction == TBN_DOWN) - e_action = GHOST_kEventButtonDown; - else - e_action = GHOST_kEventButtonUp; - - printf(" button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); - - GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); - - system->pushEvent(e); - } - #else // absolute buttons mode UINT diff = prevButtons ^ packet.pkButtons; if (diff) { @@ -607,7 +595,6 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) prevButtons = packet.pkButtons; } - #endif else { GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); @@ -643,77 +630,17 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial PACKET packet; func_Packet(context, serialNumber, &packet); - // try one way to classify cursor - UINT cursorType = (packet.pkCursor - cursorBase) % cursorCount; - printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursorType); - switch (cursorType) - { - case 0: // older Intuos tablets can track two cursors at once - case 3: // so we test for both here - activeTool.type = TABLET_MOUSE; - break; - case 1: - case 4: - activeTool.type = TABLET_PEN; - break; - case 2: - case 5: - activeTool.type = TABLET_ERASER; - break; - default: - activeTool.type = TABLET_NONE; - } - -//#if 0 - // now try another way - func_Info(WTI_CURSORS + packet.pkCursor, CSR_TYPE, &cursorType); - switch (cursorType & 0xf06) - { - case 0x802: - puts("general stylus"); - break; - case 0x902: - puts("airbrush"); - break; - case 0x804: - puts("art pen"); - break; - case 0x004: - puts("4D mouse"); - break; - case 0x006: - puts("5-button puck"); - break; - default: - puts("???"); - } -//#endif - - WTPKT toolData; - func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); - // discard any stray capabilities - // (sometimes cursors claim to be able to do things - // that their tablet doesn't support) - toolData &= (allTools|someTools); - // only report the 'special' bits that distinguish this cursor from the rest - puts("packet support"); print(toolData & someTools); - putchar('\n'); + for (std::vector::iterator i = tablets.begin(); i != tablets.end(); ++i) + if (i->ownsCursor(packet.pkCursor)) + { + activeTablet = &(*i); + activeTool = i->toolForCursor(packet.pkCursor); - if (activeTool.type == TABLET_MOUSE) - { - // don't always trust CSR_PKTDATA! - activeTool.hasPressure = false; - activeTool.hasTilt = false; - } - else - { - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; - // activeTool.hasTilt = toolData & tiltMask; - } + // remember user's custom button assignments for this tool + func_Info(WTI_CURSORS + packet.pkCursor, CSR_SYSBTNMAP, sysButtonMap); - // remember user's custom button assignments for this tool - func_Info(WTI_CURSORS + packet.pkCursor, CSR_SYSBTNMAP, sysButtonMap); + break; + } } } @@ -722,10 +649,10 @@ void GHOST_TabletManagerWin32::dropTool() activeTool.type = TABLET_NONE; activeTool.hasPressure = false; activeTool.hasTilt = false; - + prevMouseX = prevMouseY = 0; prevButtons = 0; - + activeWindow = NULL; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index df6f43d0460..eda2ed9611a 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -7,21 +7,16 @@ #define _WIN32_WINNT 0x501 // require Windows XP or newer #define WIN32_LEAN_AND_MEAN #include -#include "wintab.h" #include #include - #include "GHOST_Types.h" + class GHOST_WindowWin32; -// BEGIN from Wacom's Utils.h -typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); -typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); -typedef BOOL ( API * WTCLOSE ) ( HCTX ); -typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); -typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); -typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); -// END +#include "wintab.h" +#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION) +#define PACKETMODE (0) +#include "pktdef.h" // TabletToolData (and its components) are meant to replace GHOST_TabletData // and its customdata analogue in the window manager. For now it's confined to the @@ -49,12 +44,11 @@ typedef struct } TabletToolData; - -// "Tablet" structure is not active by pencils down -// but will be soon. - -struct Tablet +class Tablet { + int id; + TCHAR name[40]; + bool hasPressure; float pressureScale; @@ -70,38 +64,28 @@ struct Tablet WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) WTPKT someTools; // extra info available from only some tools - bool ownsCursor(UINT x) - { return (x - cursorBase) < cursorCount; } +public: + Tablet(int tabletID); + bool ownsCursor(int cursor); + TabletTool toolForCursor(int cursor); + + void attachData(PACKET const&, TabletToolData&); }; class GHOST_TabletManagerWin32 { - // the Wintab library - HMODULE lib_Wintab; - - // WinTab function pointers - WTOPENA func_Open; - WTCLOSE func_Close; - WTINFOA func_Info; - WTQUEUESIZESET func_QueueSizeSet; - WTPACKETSGET func_PacketsGet; - WTPACKET func_Packet; - - void getExtraInfo(); // to help support new/untested tablets + void getHardwareInfo(); // to help support new/untested tablets // tablet attributes - bool hasPressure; - float pressureScale; - bool hasTilt; - float azimuthScale; - float altitudeScale; -// float tiltScaleX; -// float tiltScaleY; -// UINT tiltMask; - UINT cursorCount; - UINT cursorBase; - WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) - WTPKT someTools; // extra info available from only some tools +// bool hasPressure; +// float pressureScale; +// bool hasTilt; +// float azimuthScale; +// float altitudeScale; +// UINT cursorCount; +// UINT cursorBase; +// WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) +// WTPKT someTools; // extra info available from only some tools // book-keeping std::map contexts; @@ -110,6 +94,7 @@ class GHOST_TabletManagerWin32 std::vector tablets; GHOST_WindowWin32* activeWindow; + Tablet* activeTablet; TabletTool activeTool; BYTE sysButtonMap[32]; // user's custom button assignments for active tool @@ -117,7 +102,6 @@ class GHOST_TabletManagerWin32 int prevMouseY; UINT prevButtons; - void convertTilt(ORIENTATION const&, TabletToolData&); bool convertButton(const UINT button, GHOST_TButtonMask&); public: -- cgit v1.2.3 From 50186191d998d6ab51b547d94461c8d0625f3ce0 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 21 Jan 2011 09:56:41 +0000 Subject: enabled multithread GL engine + minor cleanup --- intern/ghost/intern/GHOST_SystemCocoa.h | 6 +++--- intern/ghost/intern/GHOST_WindowCocoa.mm | 37 +++++++++++--------------------- 2 files changed, 16 insertions(+), 27 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index de835ad7768..09af9387951 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -53,7 +53,7 @@ public: * Constructor. */ GHOST_SystemCocoa(); - + /** * Destructor. */ @@ -263,7 +263,7 @@ protected: * @return Indication whether the event was handled. */ GHOST_TSuccess handleTabletEvent(void *eventPtr); - + /** * Helps handleTabletEvent function. */ @@ -336,7 +336,7 @@ protected: /** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */ bool m_isGestureInProgress; - + NSAutoreleasePool* m_pool; }; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index aea59de51cd..5bb85eaf1e7 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -34,7 +34,7 @@ #include #endif -#include +#include // standard OpenGL + Mac CGL #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" @@ -321,7 +321,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( return; } - [m_window setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; + [m_window setSystem:ghostSystem ghostWindow:this]; // Forbid to resize the window below the blender defined minimum one [m_window setContentMinSize:NSMakeSize(320,240)]; @@ -400,7 +400,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( activateDrawingContext(); CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; - [windowDelegate setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; + [windowDelegate setSystem:ghostSystem ghostWindow:this]; [m_window setDelegate:windowDelegate]; [m_window setAcceptsMouseMovedEvents:YES]; @@ -419,7 +419,6 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() { if (m_customCursor) delete m_customCursor; -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView release]; if (m_window) { @@ -434,8 +433,6 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - -// [pool drain]; } #pragma mark accessors @@ -851,7 +848,6 @@ GHOST_TSuccess GHOST_WindowCocoa::swapBuffers() } } -// [m_pool drain]; // needed to put this in a function that is called regularly return success; } @@ -872,12 +868,10 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() { if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { if (m_openGLContext != nil) { -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext makeCurrentContext]; // Disable AA by default if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB); -// [pool drain]; return GHOST_kSuccess; } } @@ -889,15 +883,9 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp { GHOST_TSuccess success = GHOST_kFailure; -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSOpenGLPixelFormat *pixelFormat; NSOpenGLContext *tmpOpenGLContext; - /***** Multithreaded opengl code : uncomment for enabling - CGLContextObj cglCtx; - */ - switch (type) { case GHOST_kDrawingContextTypeOpenGL: if (!getValid()) break; @@ -910,20 +898,21 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp break; } - //Switch openGL to multhreaded mode - /******* Multithreaded opengl code : uncomment for enabling */ - cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj]; + /******* Multithreaded OpenGL code : uncomment for enabling */ + CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj]; if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError) - printf("\nSwitched openGL to multithreaded mode"); + printf("\nUsing multithreaded OpenGL engine.\n"); if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext; -#ifdef WAIT_FOR_VSYNC - { + + #ifdef WAIT_FOR_VSYNC + { GLint swapInt = 1; /* wait for vsync, to avoid tearing artifacts */ [tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; - } -#endif + } + #endif + [m_openGLView setOpenGLContext:tmpOpenGLContext]; [tmpOpenGLContext setView:m_openGLView]; @@ -937,7 +926,7 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp default: break; } -// [pool drain]; + return success; } -- cgit v1.2.3 From 6132f8c4b49991ad7c60e15bfda6360a95a234aa Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 21 Jan 2011 10:11:26 +0000 Subject: applied Linux SpaceNav patch from Rafael Ortis --- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- intern/ghost/intern/GHOST_NDOFManagerX11.h | 58 ++++++++++++++++++++++++++++-- intern/ghost/intern/GHOST_SystemX11.cpp | 25 ++++++++----- intern/ghost/intern/GHOST_SystemX11.h | 14 ++++++++ intern/ghost/intern/GHOST_WindowX11.cpp | 20 +++++++++-- 5 files changed, 105 insertions(+), 14 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 9d0bfa3b789..f4adb4cab1d 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -45,7 +45,7 @@ public: // processes most recent raw data into an NDOFMotion event and sends it // returns whether an event was sent - bool sendMotionEvent(); + virtual bool sendMotionEvent(); protected: GHOST_System& m_system; diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index 8f9c819a481..4c89bfe0ca6 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -24,21 +24,75 @@ #define _GHOST_NDOFMANAGERX11_H_ #include "GHOST_NDOFManager.h" - +#include "GHOST_Types.h" +#include "GHOST_WindowX11.h" +#include "GHOST_EventNDOF.h" +#include +#include class GHOST_NDOFManagerX11 : public GHOST_NDOFManager { +GHOST_WindowX11 * m_ghost_window_x11; + public: GHOST_NDOFManagerX11(GHOST_System& sys) : GHOST_NDOFManager(sys) {} + void setGHOSTWindowX11(GHOST_WindowX11 * w){ + if (m_ghost_window_x11 == NULL) + m_ghost_window_x11 = w; + } + + GHOST_WindowX11 * getGHOSTWindowX11(){ + return m_ghost_window_x11; + } + // whether multi-axis functionality is available (via the OS or driver) // does not imply that a device is plugged in or being used bool available() { // never available since I've not yet written it! - return false; + return true; + } + + virtual bool sendMotionEvent() + { + if (m_atRest) + return false; + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, getGHOSTWindowX11()); + GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); + + const float scale = 1.f/350.f; // SpaceNavigator sends +/- 350 usually + // 350 according to their developer's guide; others recommend 500 as comfortable + + // possible future enhancement + // scale *= m_sensitivity; + + data->tx = -scale * m_translation[0]; + data->ty = scale * m_translation[1]; + data->tz = scale * m_translation[2]; + + data->rx = scale * m_rotation[0]; + data->ry = scale * m_rotation[1]; + data->rz = scale * m_rotation[2]; + + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + m_prevMotionTime = m_motionTime; + + printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + + if (!m_system.pushEvent(event)) + return false; + + // 'at rest' test goes at the end so that the first 'rest' event gets sent + m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && + m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; + + return true; } }; diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index dc519039af6..b389d25a7fe 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -267,6 +267,7 @@ createWindow( m_windowManager->addWindow(window); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + } else { delete window; @@ -631,10 +632,11 @@ GHOST_SystemX11::processEvent(XEvent *xe) ); } else #endif - if (sNdofInfo.currValues) { + if (m_ndofManager->available()) { + // static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; - if (xcme.message_type == sNdofInfo.motionAtom) - { + if (xcme.message_type == sNdofInfo.motionAtom + || xcme.message_type == motion_event){ // data.changed = 1; // data.delta = xcme.data.s[8] - data.time; // data.time = xcme.data.s[8]; @@ -646,9 +648,9 @@ GHOST_SystemX11::processEvent(XEvent *xe) // data.rz =-xcme.data.s[7]; short t[3], r[3]; - t[0] = xcme.data.s[2] >> 2; - t[1] = xcme.data.s[3] >> 2; - t[2] = xcme.data.s[4] >> 2; + t[0] = xcme.data.s[2]; + t[1] = xcme.data.s[3]; + t[2] = xcme.data.s[4]; r[0] = xcme.data.s[5]; r[1] = xcme.data.s[6]; r[2] =-xcme.data.s[7]; @@ -663,7 +665,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) // GHOST_kEventNDOFMotion, // window, data); - } else if (xcme.message_type == sNdofInfo.btnPressAtom) { + } else if (xcme.message_type == sNdofInfo.btnPressAtom + || xcme.message_type == button_press_event) { // data.changed = 2; // data.delta = xcme.data.s[8] - data.time; // data.time = xcme.data.s[8]; @@ -803,7 +806,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) XFlush(m_display); break; } - + default: { if(xe->type == window->GetXTablet().MotionEvent) { @@ -1505,3 +1508,9 @@ const GHOST_TUns8* GHOST_SystemX11::getBinaryDir() const return NULL; } +void GHOST_SystemX11::createNDOFAtoms(Display * display){ + motion_event = XInternAtom(display, "MotionEvent", True); + button_press_event = XInternAtom(display, "ButtonPressEvent", True); + button_release_event = XInternAtom(display, "ButtonReleaseEvent", True); + command_event = XInternAtom(display, "CommandEvent", True); +} diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index e4b02d192e8..4479dca5ecd 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -214,6 +214,12 @@ public: unsigned char **txt, unsigned long *len, unsigned int *context) const; + /** + * Create the atoms used by ndof events + * @param display Current display + */ + void createNDOFAtoms(Display * display); + /** * Returns unsinged char from CUT_BUFFER0 * @param selection Get selection, X11 only feature @@ -276,6 +282,14 @@ public: Atom m_incr; Atom m_utf8_string; + /** + * Atoms for NDOF + */ + Atom motion_event; + Atom button_press_event; + Atom button_release_event; + Atom command_event; + private : Display * m_display; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 60e12ff78df..5ce5a66bfba 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -35,6 +35,10 @@ #include #include +// libspnav +#include +#include "GHOST_NDOFManagerX11.h" + #if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX) #include #endif @@ -269,6 +273,11 @@ GHOST_WindowX11( CWBorderPixel|CWColormap|CWEventMask, &xattributes ); + if (spnav_x11_open(m_display, m_window) == -1) { + fprintf(stderr, "failed to connect to the space navigator daemon\n"); + } else { + m_system->createNDOFAtoms(m_display); + } } else { Window root_return; @@ -297,12 +306,12 @@ GHOST_WindowX11( m_visual->visual, CWBorderPixel|CWColormap|CWEventMask, &xattributes - ); + + ); XSelectInput(m_display , parentWindow, SubstructureNotifyMask); - } - + /* * One of the problem with WM-spec is that can't set a property * to a window that isn't mapped. That is why we can't "just @@ -428,6 +437,8 @@ GHOST_WindowX11( XMapWindow(m_display, m_window); GHOST_PRINT("Mapped window\n"); + + ((GHOST_NDOFManagerX11 *)m_system->getNDOFManager())->setGHOSTWindowX11(this);; XFlush(m_display); } @@ -1258,6 +1269,9 @@ GHOST_WindowX11:: if(m_xtablet.StylusDevice) XCloseDevice(m_display, m_xtablet.StylusDevice); + /*close ndof */ + spnav_close(); + if(m_xtablet.EraserDevice) XCloseDevice(m_display, m_xtablet.EraserDevice); -- cgit v1.2.3