-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmapmywindows.c
193 lines (177 loc) · 5.62 KB
/
mapmywindows.c
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <getopt.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <X11/Xlib.h>
#include <xdo.h>
#include "xkeymacro/xkeymacro.h"
#define VERSION "0.1"
struct window_node {
Window wid;
int x;
int y;
struct window_node *prev;
struct window_node *next;
};
void noreturn clean_exit(int signal);
void noreturn print_help(bool error, char *program_name);
void process_cmdline_options(int argc, char *argv[]);
void hide_window(void);
void show_window(void);
struct XKeyMacroInstance *xkeymacro_instance;
xdo_t *xdo_instance;
struct window_node *current_window = NULL;
char *hide_shortcut = "Ctrl+Shift+F7";
char *show_shortcut = "Ctrl+Shift+F8";
char *exit_shortcut = "Ctrl+Shift+F9";
int main(int argc, char *argv[]) {
// Process the supplied command-line options
process_cmdline_options(argc, argv);
// Establish connection with X display server and get the current X display
Display *display = XOpenDisplay(NULL);
if (display == NULL) {
puts("Failed to get current X display");
return EXIT_FAILURE;
}
xkeymacro_instance = xkeymacro_new_instance(display);
// Create a new xdo instance
xdo_instance = xdo_new_with_opened_display(display, NULL, true);
if (xdo_instance == NULL) {
puts("Failed to start xdo!");
return EXIT_FAILURE;
};
// Grab the keys (keyboard shortcuts/macros)
printf("Hide shortcut: %s\n", hide_shortcut);
struct XKeyMacro *hide_macro = xkeymacro_add_simple(xkeymacro_instance, hide_shortcut);
printf("Show shortcut: %s\n", show_shortcut);
struct XKeyMacro *show_macro = xkeymacro_add_simple(xkeymacro_instance, show_shortcut);
printf("Exit shortcut: %s\n", exit_shortcut);
struct XKeyMacro *exit_macro = xkeymacro_add_simple(xkeymacro_instance, exit_shortcut);
// Register signal handler
signal(SIGTERM, clean_exit);
signal(SIGINT, clean_exit);
// Wait for events (X event loop)
struct XKeyMacro *macro;
while (true) {
macro = xkeymacro_next_event(xkeymacro_instance);
if (macro == hide_macro) {
hide_window();
} else if (macro == show_macro) {
show_window();
} else if (macro == exit_macro) {
// Cleanup and exit
clean_exit(0);
}
}
}
void noreturn clean_exit(int signal) {
xkeymacro_free(xkeymacro_instance);
xdo_free(xdo_instance);
puts("Exiting!");
exit(EXIT_SUCCESS);
}
void noreturn print_help(bool error, char *program_name) {
if (!error) puts(
"mapmywindows - A small progarm to show and hide windows in X window system"
);
printf("\nUsage: %s [OPTION]\n", program_name);
puts(
"\n"
"Options:\n"
" -d, --hide-key Set the hide shortcut/macro (Default: Ctrl+Shift+F7)\n"
" -s, --show-key Set the show shortcut/macro (Default: Ctrl+Shift+F8)\n"
" -x, --exit-key Set the exit shortcut/macro (Default: Ctrl+Shift+F9)\n"
" -h, --help Show this help text\n"
" -v, --version Print the version\n"
"\n"
"Examples:\n"
" mapmywindows -d \"Ctrl+Shift+F1\" -s \"Ctrl+Shift+F2\" Change the default hide and show shortcuts\n"
"\n"
"Report bugs at the GitHub repository <https://github.com/TheDcoder/mapmywindows>"
);
exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
}
void process_cmdline_options(int argc, char *argv[]) {
struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{"hide-key", required_argument, NULL, 'd'},
{"show-key", required_argument, NULL, 's'},
{"exit-key", required_argument, NULL, 'x'},
{NULL, 0, NULL, 0}
};
int option;
while ((option = getopt_long(argc, argv, "hvd:s:x:", long_options, NULL)) != -1) {
switch (option) {
case 'h':
case '?':
print_help(option == '?', argv[0]);
break;
case 'v':
puts("mapmywindows " VERSION "\n\nWritten by Damon Harris (TheDcoder)");
exit(EXIT_SUCCESS);
case 'd':
hide_shortcut = optarg;
break;
case 's':
show_shortcut = optarg;
break;
case 'x':
exit_shortcut = optarg;
break;
}
}
}
void hide_window(void) {
if (current_window == NULL) {
// Create the first node in our window list
current_window = malloc(sizeof(struct window_node));
if (current_window == NULL) {
puts("Failed to allocate memory to store the first window!");
return;
}
current_window->prev = NULL;
current_window->next = NULL;
} else {
// Create and append a new node in our window list
current_window->next = malloc(sizeof(struct window_node));
if (current_window->next == NULL) {
puts("Failed to allocate memory to store the window!");
return;
}
current_window->next->prev = current_window;
current_window = current_window->next;
current_window->next = NULL;
}
// Store the active window
xdo_get_active_window(xdo_instance, ¤t_window->wid);
// Store the window's position
xdo_get_window_location(xdo_instance, current_window->wid, ¤t_window->x, ¤t_window->y, NULL);
// Hide the window
xdo_unmap_window(xdo_instance, current_window->wid);
printf("Hidden the active window %li\n", current_window->wid);
}
void show_window(void) {
if (current_window == NULL) {
puts("No windows are hidden!");
return;
}
// Restore window
xdo_map_window(xdo_instance, current_window->wid);
// Restore the window's position
xdo_move_window(xdo_instance, current_window->wid, current_window->x, current_window->y);
printf("Shown the hidden window %li\n", current_window->wid);
if (current_window->prev == NULL) {
// Delete the only node in our list and reset it
free(current_window);
current_window = NULL;
} else {
// Delete the current node and move the pointer to previous node
current_window = current_window->prev;
free(current_window->next);
current_window->next = NULL;
}
}