Skip to content

Commit

Permalink
Implementing MacOS.
Browse files Browse the repository at this point in the history
  • Loading branch information
SySyAli committed Jan 6, 2024
1 parent ea82a62 commit 9396b07
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 20 deletions.
40 changes: 25 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ endif()
# include sqlite3
find_package(SQLite3 REQUIRED)

# find X11 - linux
find_package(X11 REQUIRED)

# Include directories
include_directories(${SQLite3_INCLUDE_DIRS})
if(X11_FOUND)
include_directories(${X11_INCLUDE_DIR})

# Include X11 for Linux
if(UNIX AND NOT APPLE)
find_package(X11 REQUIRED)
if(X11_FOUND)
include_directories(${X11_INCLUDE_DIR})
endif()
endif()

# include testing
Expand All @@ -48,21 +50,24 @@ add_executable(desktop_screentime main.cpp
IWindowInterface.cpp
)

# Link SQLite3 and possibly X11 and pthread to the executable
if(MSVC)
# Using Microsoft Visual C++
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES})
else()
# Assuming GCC or Clang
# Link SQLite3 to the executable
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES})


# Link pthread and X11 for Linux
if(UNIX AND NOT APPLE)
if(X11_FOUND)
# Link both SQLite3 and X11 (and pthread for Linux)
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES} ${X11_LIBRARIES} pthread)
target_link_libraries(desktop_screentime PRIVATE ${X11_LIBRARIES} pthread)
else()
# Link only SQLite3 and pthread (for Linux without X11)
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES} pthread)
target_link_libraries(desktop_screentime PRIVATE pthread)
endif()
endif()

# Link Application Services for macOS
if(APPLE)
target_link_libraries(desktop_screentime "-framework ApplicationServices")
endif()

# Testing Executable
# Define the source files and dependencies for the executable
set(SOURCE_FILES
Expand All @@ -83,4 +88,9 @@ target_link_libraries(tests gtest gtest_main ${SQLite3_LIBRARIES})
if(UNIX AND NOT APPLE)
target_link_libraries(tests ${X11_LIBRARIES} pthread)
endif()
# Link Application Services for macOS
if(APPLE)
target_link_libraries(tests "-framework ApplicationServices")
endif()

target_include_directories(tests PRIVATE ${SQLite3_INCLUDE_DIRS})
76 changes: 71 additions & 5 deletions IWindowInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#elif __linux__
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#elif __APPLE__
#include <ApplicationServices/ApplicationServices.h>
#endif

IWindowInterface::IWindowInterface()
Expand Down Expand Up @@ -168,8 +170,72 @@ void LinuxTracker::startTracking()
}
#endif

// TODO
void MacOSTracker::startTracking()
{
throw std::runtime_error("MacOS has not been implemented yet!");
}
#ifdef __APPLE__

std::string getActiveWindowTitleMac() {
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
if (windowList) {
for (CFIndex i = 0; i < CFArrayGetCount(windowList); i++) {
CFDictionaryRef windowInfo = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, i);
CFNumberRef windowLayer = (CFNumberRef)CFDictionaryGetValue(windowInfo, kCGWindowLayer);
int layer;
CFNumberGetValue(windowLayer, kCFNumberIntType, &layer);
if (layer == 0) { // Check if it's the active window layer
CFStringRef windowTitle = (CFStringRef)CFDictionaryGetValue(windowInfo, kCGWindowName);
if (windowTitle) {
char title[256];
CFStringGetCString(windowTitle, title, 256, kCFStringEncodingUTF8);
CFRelease(windowList);
return std::string(title);
}
}
}
CFRelease(windowList);
}
return "";
}

void MacOSTracker::startTracking() {
AppEntry prevEntry;
while (tracking) {
std::string title = getActiveWindowTitleMac();
char dt[26];
auto curTime = std::chrono::system_clock::now();
const std::time_t t_c = std::chrono::system_clock::to_time_t(curTime);

// unix based systems - ctime_r
char* res_s = ctime_r(&t_c, dt);
if (!res_s) {
throw std::runtime_error("Error converting time");
}
if (!title.empty()) {
// handle the first entry
if (prevEntry.isEmpty()) {
std::cout << "Starting time for " << title << " : " << dt;
prevEntry.setTitle(title);
prevEntry.setStartTime(curTime);
} else if (prevEntry.getTitle() != title) {
prevEntry.setEndTime(curTime);
// Calculate the duration in seconds
auto duration = std::chrono::duration_cast<std::chrono::seconds>(
prevEntry.getEndTime() - prevEntry.getStartTime());

std::cout << "Ending time for " << prevEntry.getTitle() << " : " << dt;
std::cout << "Duration for " << prevEntry.getTitle() << " : " << duration.count()
<< " seconds" << std::endl;

// insert the appEntry
dbManager.insertData(prevEntry);

// figure out the time spent at the website
std::cout << "Starting time for " << title << " : " << dt << std::endl;
prevEntry.setTitle(title);
prevEntry.setStartTime(curTime);
}
}

std::this_thread::sleep_for(std::chrono::seconds(1));
}

}
#endif

0 comments on commit 9396b07

Please sign in to comment.