Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

windows support #22

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/EmojiPickerSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ std::vector<Emoji> EmojiPickerSettings::recentEmojis() {
recentEmojis = readQSettingsArrayToStdVector<Emoji>(*this, prefix, handler);
}

return std::move(recentEmojis);
return recentEmojis;
}
void EmojiPickerSettings::setRecentEmojis(const std::vector<Emoji>& recentEmojis) {
auto prefix = "recentEmojis";
Expand Down Expand Up @@ -354,7 +354,11 @@ void EmojiPickerSettings::setWindowOpacity(double windowOpacity) {
}

bool EmojiPickerSettings::swapEnterAndShiftEnter() const {
#ifdef __linux__
return value("swapEnterAndShiftEnter", false).toBool();
#elif _WIN32
return true;
#endif
}
void EmojiPickerSettings::setSwapEnterAndShiftEnter(bool swapEnterAndShiftEnter) {
setValue("swapEnterAndShiftEnter", swapEnterAndShiftEnter);
Expand Down
159 changes: 71 additions & 88 deletions src/crossdo.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#pragma once

#ifdef __linux__
#ifdef __cplusplus
extern "C" {
#endif

#ifdef __linux__
#include "xdo.h"
#ifdef __cplusplus
}
#endif
#elif _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_WIN10
Expand All @@ -30,12 +32,12 @@ extern "C" {
#define NOGDI 1
#define NOKERNEL 1
// #define NOUSER 1
#define NONLS 1
// #define NONLS 1
#define NOMB 1
#define NOMEMMGR 1
#define NOMETAFILE 1
#define NOMINMAX 1
#define NOMSG 1
// #define NOMSG 1
#define NOOPENFILE 1
#define NOSCROLL 1
#define NOSERVICE 1
Expand All @@ -53,6 +55,10 @@ extern "C" {
// https://docs.microsoft.com/en-us/windows/win32/winprog/using-the-windows-headers
#include "windows.h"
#include "windowsx.h"
#include "ole2.h"
#include "oleacc.h"
#include "UIAutomation.h"
#include "stringapiset.h"
#endif

#ifdef __linux__
Expand All @@ -65,15 +71,24 @@ typedef HWND window_t;
typedef xdo_t crossdo_t;
#elif _WIN32
typedef struct {
int nothing;
IUIAutomation* ui_automation;
IUIAutomationElement* ui_element;
} crossdo_t;
#endif

crossdo_t* crossdo_new() {
#ifdef __linux__
return xdo_new(NULL);
#elif _WIN32
return (crossdo_t*)malloc(sizeof(crossdo_t));
if (FAILED(CoInitialize(NULL))) {
printf("CoInitialize(...) failed");
return NULL;
}

crossdo_t* crossdo = (crossdo_t*)malloc(sizeof(crossdo_t));
crossdo->ui_automation = NULL;
crossdo->ui_element = NULL;
return crossdo;
#endif
}

Expand All @@ -82,11 +97,13 @@ void crossdo_free(crossdo_t* crossdo) {
xdo_free(crossdo);
#elif _WIN32
free(crossdo);

CoUninitialize();
#endif
}

int crossdo_get_mouse_location2(
const crossdo_t* crossdo, int* x_ret, int* y_ret, int* screen_num_ret, window_t* window_ret) {
crossdo_t* crossdo, int* x_ret, int* y_ret, int* screen_num_ret, window_t* window_ret) {
#ifdef __linux__
return xdo_get_mouse_location2(crossdo, x_ret, y_ret, screen_num_ret, window_ret);
#elif _WIN32
Expand All @@ -110,7 +127,7 @@ int crossdo_get_mouse_location2(
}

int crossdo_get_caret_location2(
const crossdo_t* crossdo, int* x_ret, int* y_ret, int* screen_num_ret, window_t* window_ret) {
crossdo_t* crossdo, int* x_ret, int* y_ret, int* screen_num_ret, window_t* window_ret) {
#ifdef __linux__
*x_ret = 0;
*y_ret = 0;
Expand All @@ -128,7 +145,7 @@ int crossdo_get_caret_location2(
#endif
}

int crossdo_get_pid_window(const crossdo_t* crossdo, window_t window) {
int crossdo_get_pid_window(crossdo_t* crossdo, window_t window) {
#ifdef __linux__
return xdo_get_pid_window(crossdo, window);
#elif _WIN32
Expand All @@ -139,124 +156,90 @@ int crossdo_get_pid_window(const crossdo_t* crossdo, window_t window) {
#endif
}

int crossdo_get_active_window(const crossdo_t* crossdo, window_t* window_ret) {
int crossdo_get_active_window(crossdo_t* crossdo, window_t* window_ret) {
#ifdef __linux__
return xdo_get_active_window(crossdo, window_ret);
#elif _WIN32
*window_ret = GetForegroundWindow();

if (crossdo->ui_element == NULL) {
if (FAILED(CoCreateInstance(
__uuidof(CUIAutomation8), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&crossdo->ui_automation)))) {
printf("CoCreateInstance(__uuidof(CUIAutomation8), ...) failed");
return -1;
}

if (FAILED(crossdo->ui_automation->GetFocusedElement(&crossdo->ui_element))) {
printf("ui_automation->GetFocusedElement(...) failed");
return -1;
}
}

return 0;
#endif
}

int crossdo_activate_window(const crossdo_t* crossdo, window_t window) {
int crossdo_activate_window(crossdo_t* crossdo, window_t window) {
#ifdef __linux__
return xdo_activate_window(crossdo, window);
#elif _WIN32
window_t current_window = GetForegroundWindow();

unsigned long process_thread = GetProcessId();
unsigned long current_thread = GetWindowThreadProcessId(current_window, NULL);
unsigned long window_thread = GetWindowThreadProcessId(window, NULL);

if (process_thread == current_thread && process_thread != window_thread) {
AttachThreadInput(window_thread, process_thread, TRUE);
}

SetActiveWindow(window);

if (process_thread == window_thread && process_thread != current_thread) {
AttachThreadInput(current_thread, process_thread, FALSE);
}

return 0;
#endif
}

int crossdo_wait_for_window_active(const crossdo_t* crossdo, window_t window, int active) {
int crossdo_wait_for_window_active(crossdo_t* crossdo, window_t window, int active) {
#ifdef __linux__
return xdo_wait_for_window_active(crossdo, window, active);
#elif _WIN32
Sleep(25);

return 0;
#endif
}

int crossdo_enter_text_window(const crossdo_t* crossdo, window_t window, const char* string, unsigned int delay) {
int crossdo_enter_text_window(crossdo_t* crossdo, window_t window, const char* string, unsigned int delay) {
#ifdef __linux__
return xdo_enter_text_window(crossdo, window, string, delay);
#elif _WIN32
// string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

size_t input_len = strlen(string) * 2;
INPUT* input = (INPUT*)malloc(sizeof(INPUT) * input_len);

window_t current_window = GetForegroundWindow();
unsigned long current_thread = GetWindowThreadProcessId(current_window, NULL);
unsigned long window_thread = GetWindowThreadProcessId(window, NULL);

AttachThreadInput(window_thread, current_thread, TRUE);

// SetActiveWindow(window);

for (int i = 0; i < (input_len / 2); i++) {
INPUT* down = &input[(i * 2) + 0];
INPUT* up = &input[(i * 2) + 1];

down->type = INPUT_KEYBOARD;
down->ki.wScan = string[i];
down->ki.time = 0;
down->ki.dwExtraInfo = NULL;
down->ki.wVk = 0;
down->ki.dwFlags = KEYEVENTF_UNICODE | 0;

up->type = INPUT_KEYBOARD;
up->ki.wScan = string[i];
up->ki.time = 0;
up->ki.dwExtraInfo = NULL;
up->ki.wVk = 0;
up->ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;

// INPUT input[2];

// input[0].type = INPUT_KEYBOARD;
// input[0].ki.wScan = string[i];
// input[0].ki.time = 0;
// input[0].ki.dwExtraInfo = NULL;
// input[0].ki.wVk = 0;
// input[0].ki.dwFlags = KEYEVENTF_UNICODE | 0;

// input[1].type = INPUT_KEYBOARD;
// input[1].ki.wScan = string[i];
// input[1].ki.time = 0;
// input[1].ki.dwExtraInfo = NULL;
// input[1].ki.wVk = 0;
// input[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;

// SendInput(2, input, sizeof(INPUT));
IUnknown* value_pattern_tmp;
if (FAILED(crossdo->ui_element->GetCurrentPattern(UIA_ValuePatternId, &value_pattern_tmp))) {
printf("ui_element->GetCurrentPattern(UIA_ValuePatternId, ...) failed");
return -1;
}

SendInput(input_len, input, sizeof(INPUT));
IUIAutomationValuePattern* value_pattern = (IUIAutomationValuePattern*)value_pattern_tmp;

SetActiveWindow(current_window);
BSTR current_bstr;
if (FAILED(value_pattern->get_CurrentValue(&current_bstr))) {
printf("value_pattern->get_CurrentValue(...) failed");
return -1;
}
int current_wslen = SysStringLen(current_bstr);

AttachThreadInput(window_thread, current_thread, FALSE);
int string_wslen = MultiByteToWideChar(CP_UTF8, 0, string, strlen(string), 0, 0);
BSTR string_bstr = SysAllocStringLen(0, string_wslen);
MultiByteToWideChar(CP_UTF8, 0, string, strlen(string), string_bstr, string_wslen);

free(input);
BSTR new_bstr = SysAllocStringLen(NULL, current_wslen + string_wslen);
memcpy(new_bstr, current_bstr, current_wslen * sizeof(OLECHAR));
memcpy(new_bstr + current_wslen, string_bstr, string_wslen * sizeof(OLECHAR));
new_bstr[current_wslen + string_wslen] = NULL;

if (FAILED(value_pattern->SetValue(new_bstr))) {
printf("value_pattern->SetValue(...) failed");
return -1;
}

SysFreeString(new_bstr);
SysFreeString(string_bstr);
SysFreeString(current_bstr);

return 0;
#endif
}

int crossdo_send_keysequence_window(const crossdo_t* crossdo, window_t window, const char* keysequence, unsigned int delay) {
int crossdo_send_keysequence_window(crossdo_t* crossdo, window_t window, const char* keysequence, unsigned int delay) {
#ifdef __linux__
return xdo_send_keysequence_window(crossdo, window, keysequence, delay);
#elif _WIN32
return 0;
#endif
}

#ifdef __cplusplus
}
#endif