1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 | // defined so that we get the stable ABI from 3.2 onwards - means we don't have to
// recompile this module for every new python version.
#define Py_LIMITED_API
// has to be included first
#include "Python.h"
#include <Windows.h>
struct Modifier {
WORD vk;
bool set;
};
static void sendCtrlV() {
INPUT ctrlV[] = {{0},{0},{0},{0}};
ctrlV[0].type = INPUT_KEYBOARD;
ctrlV[0].ki.wVk = VK_LCONTROL;
ctrlV[1].type = INPUT_KEYBOARD;
ctrlV[1].ki.wVk = 'V';
ctrlV[2].type = INPUT_KEYBOARD;
ctrlV[2].ki.wVk = 'V';
ctrlV[2].ki.dwFlags = KEYEVENTF_KEYUP;
ctrlV[3].type = INPUT_KEYBOARD;
ctrlV[3].ki.wVk = VK_LCONTROL;
ctrlV[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(sizeof(ctrlV)/sizeof(INPUT), ctrlV, sizeof(INPUT));
}
static void sendEvent(WORD vk, DWORD flags) {
INPUT in = {0};
in.type = INPUT_KEYBOARD;
in.ki.wVk = vk;
in.ki.dwFlags = flags;
SendInput(1, &in, sizeof(INPUT));
}
/*
Works as following: First record which control keys are down, make sure they are
up, then send the ctrl-v command, then reinstate original state.
If we don't do this we may get interesting results, i.e.: Ctrl+Alt+V instead of Ctrl-v won't
do what we want.
*/
static PyObject* sendPasteCommand(PyObject *self, PyObject *args) {
Modifier modifiers[] = {
{VK_MENU, 0}, /* alt key*/
{VK_CONTROL, 0},
{VK_SHIFT, 0},
{VK_LWIN, 0},
{VK_RWIN, 0},
};
for (int i = 0; i < sizeof(modifiers)/sizeof(Modifier); i++) {
Modifier& mod = modifiers[i];
if (GetAsyncKeyState(mod.vk) < 0) {
mod.set = true;
sendEvent(mod.vk, KEYEVENTF_KEYUP);
}
}
sendCtrlV();
for (int i = 0; i < sizeof(modifiers)/sizeof(Modifier); i++) {
Modifier& mod = modifiers[i];
if (mod.set) sendEvent(mod.vk, 0 /* key down */);
}
Py_RETURN_NONE;
}
/*
This only works correctly when the shortcut itself is something like ctrl-<something>,
but is faster, simpler and should work better in such situations.
*/
static PyObject* sendV(PyObject *self, PyObject *args) {
INPUT inputs[] = {{0}, {0}};
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = 'V';
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = 'V';
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(sizeof(inputs) / sizeof(INPUT), inputs, sizeof(INPUT));
Py_RETURN_NONE;
}
static PyMethodDef methods[] = { /* see http://docs.python.org/py3k/c-api/structures.html#PyMethodDef */
{"send_paste", /* name of python function in module */
sendPasteCommand, /* pointer to c function */
METH_VARARGS, /* parameters are provided as tuple, if METH_VARARGS | METH_KEYWORDS is
specified as a third parameter a dictionary of keywords is passed */
"sends ctrl-v to current application" },
{"send_paste_simple",
sendV,
METH_VARARGS,
"sends baiscally only a 'v' to the application. This is much simpler and faster "
"than the complete version (so should work better), but also only works if the shortcut "
"is only ctrl-something"
},
{NULL, NULL, 0, NULL} /* guard */
};
static struct PyModuleDef sendpastemodule = {
PyModuleDef_HEAD_INIT,
"sendpaste", /* name of module */
"", /* doc string */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables.
state can be accessed by PyModule_GetState() */
methods,
NULL, /* m_reload: unused, should be null */
NULL, /* m_traverse: A traversal function to call during GC traversal of the module object,
or NULL if not needed. */
NULL, /* m_clear: A clear function to call during GC clearing of the module object,
or NULL if not needed. */
NULL /* m_free: A function to call during deallocation of the module object,
or NULL if not needed. */
};
PyMODINIT_FUNC PyInit_sendpaste() {
return PyModule_Create(&sendpastemodule);
}
|