diff options
Diffstat (limited to 'intern/ghost/intern')
-rw-r--r-- | intern/ghost/intern/GHOST_Path-api.cpp | 6 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.mm | 11 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemPathsCocoa.h | 6 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemPathsCocoa.mm | 52 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemPathsUnix.cpp | 59 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemPathsUnix.h | 6 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemPathsWin32.cpp | 45 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemPathsWin32.h | 6 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 4 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWayland.cpp | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 69 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.h | 14 |
12 files changed, 243 insertions, 37 deletions
diff --git a/intern/ghost/intern/GHOST_Path-api.cpp b/intern/ghost/intern/GHOST_Path-api.cpp index df3592fb5e5..c82e9819f3c 100644 --- a/intern/ghost/intern/GHOST_Path-api.cpp +++ b/intern/ghost/intern/GHOST_Path-api.cpp @@ -50,6 +50,12 @@ const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr) return systemPaths ? systemPaths->getUserDir(version, versionstr) : NULL; /* shouldn't be NULL */ } +const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type) +{ + GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); + return systemPaths ? systemPaths->getUserSpecialDir(type) : NULL; /* shouldn't be NULL */ +} + const GHOST_TUns8 *GHOST_getBinaryDir() { GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index d5b8311349b..d7dbfbe8813 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -82,8 +82,8 @@ static GHOST_TButtonMask convertButton(int button) /** * Converts Mac rawkey codes (same for Cocoa & Carbon) * into GHOST key codes - * \param rawCode The raw physical key code - * \param recvChar the character ignoring modifiers (except for shift) + * \param rawCode: The raw physical key code + * \param recvChar: the character ignoring modifiers (except for shift) * \return Ghost key code */ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) @@ -783,7 +783,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet /** * Dispose of a context. - * \param context Pointer to the context to be disposed. + * \param context: Pointer to the context to be disposed. * \return Indication of success. */ GHOST_TSuccess GHOST_SystemCocoa::disposeContext(GHOST_IContext *context) @@ -1730,13 +1730,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); + NSPoint delta = [[cocoawindow contentView] convertPointToBacking:NSMakePoint(dx, dy)]; pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, - dx, - dy, + delta.x, + delta.y, [event isDirectionInvertedFromDevice])); } } break; diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h index 188f6f02286..14633d46f03 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h @@ -56,6 +56,12 @@ class GHOST_SystemPathsCocoa : public GHOST_SystemPaths { const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** + * Determine a special ("well known") and easy to reach user directory. + * \return Unsigned char string pointing to user dir (eg `~/Documents/`). + */ + const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; + + /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm index 830d58ba42c..7c6184837bf 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm @@ -21,6 +21,7 @@ #import <Foundation/Foundation.h> +#include "GHOST_Debug.h" #include "GHOST_SystemPathsCocoa.h" #pragma mark initialization/finalization @@ -89,6 +90,57 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionst return (GHOST_TUns8 *)tempPath; } +const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const +{ + static char tempPath[512] = ""; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *basePath; + NSArray *paths; + NSSearchPathDirectory ns_directory; + + switch (type) { + case GHOST_kUserSpecialDirDesktop: + ns_directory = NSDesktopDirectory; + break; + case GHOST_kUserSpecialDirDocuments: + ns_directory = NSDocumentDirectory; + break; + case GHOST_kUserSpecialDirDownloads: + ns_directory = NSDownloadsDirectory; + break; + case GHOST_kUserSpecialDirMusic: + ns_directory = NSMusicDirectory; + break; + case GHOST_kUserSpecialDirPictures: + ns_directory = NSPicturesDirectory; + break; + case GHOST_kUserSpecialDirVideos: + ns_directory = NSMoviesDirectory; + break; + default: + GHOST_ASSERT( + false, + "GHOST_SystemPathsCocoa::getUserSpecialDir(): Invalid enum value for type parameter"); + [pool drain]; + return NULL; + } + + paths = NSSearchPathForDirectoriesInDomains(ns_directory, NSUserDomainMask, YES); + + if ([paths count] > 0) + basePath = [paths objectAtIndex:0]; + else { + [pool drain]; + return NULL; + } + + strncpy( + (char *)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding], sizeof(tempPath)); + + [pool drain]; + return (GHOST_TUns8 *)tempPath; +} + const GHOST_TUns8 *GHOST_SystemPathsCocoa::getBinaryDir() const { static GHOST_TUns8 tempPath[512] = ""; diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp index ad3d490eb91..86f3a0a31fb 100644 --- a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp @@ -21,6 +21,9 @@ * \ingroup GHOST */ +#include <cstdio> +#include <sstream> + #include "GHOST_SystemPathsUnix.h" #include "GHOST_Debug.h" @@ -108,6 +111,62 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *ve } } +const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const +{ + const char *type_str; + + switch (type) { + case GHOST_kUserSpecialDirDesktop: + type_str = "DESKTOP"; + break; + case GHOST_kUserSpecialDirDocuments: + type_str = "DOCUMENTS"; + break; + case GHOST_kUserSpecialDirDownloads: + type_str = "DOWNLOAD"; + break; + case GHOST_kUserSpecialDirMusic: + type_str = "MUSIC"; + break; + case GHOST_kUserSpecialDirPictures: + type_str = "PICTURES"; + break; + case GHOST_kUserSpecialDirVideos: + type_str = "VIDEOS"; + break; + default: + GHOST_ASSERT( + false, + "GHOST_SystemPathsUnix::getUserSpecialDir(): Invalid enum value for type parameter"); + return NULL; + } + + static string path = ""; + /* Pipe stderr to /dev/null to avoid error prints. We will fail gracefully still. */ + string command = string("xdg-user-dir ") + type_str + " 2> /dev/null"; + + FILE *fstream = popen(command.c_str(), "r"); + if (fstream == NULL) { + return NULL; + } + std::stringstream path_stream; + while (!feof(fstream)) { + char c = fgetc(fstream); + /* xdg-user-dir ends the path with '\n'. */ + if (c == '\n') { + break; + } + path_stream << c; + } + if (pclose(fstream) == -1) { + perror("GHOST_SystemPathsUnix::getUserSpecialDir failed at pclose()"); + return NULL; + } + + path = path_stream.str(); + return path[0] ? (const GHOST_TUns8 *)path.c_str() : NULL; +} + const GHOST_TUns8 *GHOST_SystemPathsUnix::getBinaryDir() const { return NULL; diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.h b/intern/ghost/intern/GHOST_SystemPathsUnix.h index 8d2f26a28aa..bc9272ecd8f 100644 --- a/intern/ghost/intern/GHOST_SystemPathsUnix.h +++ b/intern/ghost/intern/GHOST_SystemPathsUnix.h @@ -54,6 +54,12 @@ class GHOST_SystemPathsUnix : public GHOST_SystemPaths { const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** + * Determine a special ("well known") and easy to reach user directory. + * \return Unsigned char string pointing to user dir (eg `~/Documents/`). + */ + const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; + + /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp index 673cbcad97e..193633b5c3e 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp @@ -22,6 +22,7 @@ */ #include "GHOST_SystemPathsWin32.h" +#include "GHOST_Debug.h" #ifndef _WIN32_IE # define _WIN32_IE 0x0501 @@ -76,6 +77,50 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionst return NULL; } +const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const +{ + GUID folderid; + + switch (type) { + case GHOST_kUserSpecialDirDesktop: + folderid = FOLDERID_Desktop; + break; + case GHOST_kUserSpecialDirDocuments: + folderid = FOLDERID_Documents; + break; + case GHOST_kUserSpecialDirDownloads: + folderid = FOLDERID_Downloads; + break; + case GHOST_kUserSpecialDirMusic: + folderid = FOLDERID_Music; + break; + case GHOST_kUserSpecialDirPictures: + folderid = FOLDERID_Pictures; + break; + case GHOST_kUserSpecialDirVideos: + folderid = FOLDERID_Videos; + break; + default: + GHOST_ASSERT( + false, + "GHOST_SystemPathsWin32::getUserSpecialDir(): Invalid enum value for type parameter"); + return NULL; + } + + static char knownpath[MAX_PATH * 3] = {0}; + PWSTR knownpath_16 = NULL; + HRESULT hResult = SHGetKnownFolderPath(folderid, KF_FLAG_DEFAULT, NULL, &knownpath_16); + + if (hResult == S_OK) { + conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3); + CoTaskMemFree(knownpath_16); + return (GHOST_TUns8 *)knownpath; + } + + CoTaskMemFree(knownpath_16); + return NULL; +} + const GHOST_TUns8 *GHOST_SystemPathsWin32::getBinaryDir() const { static char fullname[MAX_PATH * 3] = {0}; diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h index 1a1eab21bad..45e03e744a5 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.h +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h @@ -63,6 +63,12 @@ class GHOST_SystemPathsWin32 : public GHOST_SystemPaths { const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** + * Determine a special ("well known") and easy to reach user directory. + * \return Unsigned char string pointing to user dir (eg `~/Documents/`). + */ + const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const; + + /** * Determine the directory of the current binary * \return Unsigned char string pointing to the binary dir */ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 8178b9bdf1e..2bf1d0c2d35 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -422,7 +422,7 @@ finished: /** * Dispose of a context. - * \param context Pointer to the context to be disposed. + * \param context: Pointer to the context to be disposed. * \return Indication of success. */ GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context) @@ -1614,7 +1614,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, break; } case WT_PACKET: - window->updatePendingWintabEvents(); + window->updateWintabEventsSyncTime(); break; //////////////////////////////////////////////////////////////////////// // Pointer events, processed diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index fe65162d168..1e1d0814d3a 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -407,7 +407,7 @@ void GHOST_WindowWayland::setOpaque() const #endif /** - * \param type The type of rendering context create. + * \param type: The type of rendering context create. * \return Indication of success. */ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType type) diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index af02663985d..a4cbf66b22d 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -1292,7 +1292,7 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3 GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem(); - updatePendingWintabEvents(); + updateWintabEvents(); auto &pendingEvents = m_wintab.pendingEvents; size_t pendingEventSize = pendingEvents.size(); @@ -1388,6 +1388,44 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3 return GHOST_kSuccess; } +void GHOST_WindowWin32::updateWintabEvents() +{ + readWintabEvents(); + // When a Wintab device is used to leave window focus, some of it's packets are periodically not + // queued in time to be flushed. Reading packets needs to occur before expiring packets to clear + // these from the queue. + expireWintabEvents(); +} + +void GHOST_WindowWin32::updateWintabEventsSyncTime() +{ + readWintabEvents(); + + if (!m_wintab.pendingEvents.empty()) { + auto lastEvent = m_wintab.pendingEvents.back(); + m_wintab.sysTimeOffset = ::GetTickCount() - lastEvent.pkTime; + } + + expireWintabEvents(); +} + +void GHOST_WindowWin32::readWintabEvents() +{ + if (!(m_wintab.packetsGet && m_wintab.context)) { + return; + } + + auto &pendingEvents = m_wintab.pendingEvents; + + /* Get new packets. */ + const int numPackets = m_wintab.packetsGet( + m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data()); + + for (int i = 0; i < numPackets; i++) { + pendingEvents.push(m_wintab.pkts[i]); + } +} + /* Wintab (per documentation but may vary with implementation) does not update when its event * buffer is full. This is an issue because we need some synchronization point between Wintab * events and Win32 events, so we can't drain and process the queue immediately. We need to @@ -1396,17 +1434,12 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3 * mode from the Wintab API alone. There is no guaranteed ordering between Wintab and Win32 mouse * events and no documented time stamp shared between the two, so we synchronize on mouse button * events. */ -void GHOST_WindowWin32::updatePendingWintabEvents() +void GHOST_WindowWin32::expireWintabEvents() { - if (!(m_wintab.packetsGet && m_wintab.context)) { - return; - } - auto &pendingEvents = m_wintab.pendingEvents; - /* Clear outdated events from queue. */ - DWORD currTime = ::GetTickCount(); - DWORD millisTimeout = 500; + DWORD currTime = ::GetTickCount() - m_wintab.sysTimeOffset; + DWORD millisTimeout = 300; while (!pendingEvents.empty()) { DWORD pkTime = pendingEvents.front().pkTime; @@ -1417,24 +1450,6 @@ void GHOST_WindowWin32::updatePendingWintabEvents() break; } } - - /* Get new packets. */ - const int numPackets = m_wintab.packetsGet( - m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data()); - - int i = 0; - /* Don't queue outdated packets, such events can include packets that occurred before the current - * window lost and regained focus. */ - for (; i < numPackets; i++) { - DWORD pkTime = m_wintab.pkts[i].pkTime; - - if (currTime < pkTime + millisTimeout) { - break; - } - } - for (; i < numPackets; i++) { - pendingEvents.push(m_wintab.pkts[i]); - } } GHOST_TUns16 GHOST_WindowWin32::getDPIHint() diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a761d7d84dc..829bbdea051 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -486,9 +486,14 @@ class GHOST_WindowWin32 : public GHOST_Window { GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo); /** - * Updates stored pending Wintab events. + * Updates pending Wintab events and syncs Wintab time with OS time. */ - void updatePendingWintabEvents(); + void updateWintabEventsSyncTime(); + + /** + * Updates pending Wintab events. + */ + void updateWintabEvents(); GHOST_TSuccess beginFullScreen() const { @@ -629,6 +634,7 @@ class GHOST_WindowWin32 : public GHOST_Window { GHOST_TUns8 numSysButtons = 0; /** Cursors currently in contact mapped to system buttons */ DWORD sysButtonsPressed = 0; + DWORD sysTimeOffset = 0; LONG maxPressure = 0; LONG maxAzimuth = 0, maxAltitude = 0; /** Reusable buffer to read in Wintab Packets. */ @@ -642,6 +648,10 @@ class GHOST_WindowWin32 : public GHOST_Window { */ void initializeWintab(); + void readWintabEvents(); + + void expireWintabEvents(); + /** * Convert Wintab system mapped (mouse) buttons into Ghost button mask. * \param cursor: The Wintab cursor associated to the button. |