pacman database update
[cinan.git] / skripty / focus.c
blob5d59976989b0db834a7cbbeb5d3b97f4c0b3333a
1 /* gcc -Wall -pedantic -o focus focus.c -lX11 `pkg-config --cflags --libs glib-2.0` -O2 -fno-strict-aliasing */
3 #include <X11/Xlib.h>
4 #include <glib.h> /* sorting, oh my */
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <X11/Xatom.h>
9 struct display {
10 Display * display;
11 Window root;
14 struct display * display_open(const char * string) {
15 struct display * display = malloc(sizeof(struct display));
16 display->display = XOpenDisplay(NULL);
17 display->root = DefaultRootWindow(display->display);
19 return display;
22 void display_close(struct display * display) {
23 XCloseDisplay(display->display);
24 free(display);
27 long display_get_current_desktop(struct display * display) {
28 Atom actual_type_return;
29 int actual_format_return = 0;
30 unsigned long nitems_return = 0;
31 unsigned long bytes_after_return = 0;
32 long * desktop = 0;
33 long ret;
35 if (XGetWindowProperty(display->display, display->root, XInternAtom(display->display, "_NET_CURRENT_DESKTOP", False), 0, 1,
36 False, XA_CARDINAL, &actual_type_return, &actual_format_return,
37 &nitems_return, &bytes_after_return, (unsigned char**)&desktop) != Success) {
38 return 0;
40 if (actual_type_return != XA_CARDINAL || nitems_return == 0) {
41 return 0;
44 ret = desktop[0];
45 XFree(desktop);
47 return ret;
50 long window_get_desktop(struct display * display, Window window) {
51 Atom actual_type_return;
52 int actual_format_return = 0;
53 unsigned long nitems_return = 0;
54 unsigned long bytes_after_return = 0;
55 long * desktop = 0;
56 long ret = 0;
58 if (XGetWindowProperty(display->display, window, XInternAtom(display->display, "_NET_WM_DESKTOP", False), 0, 1, False, XA_CARDINAL, &actual_type_return, &actual_format_return, &nitems_return, &bytes_after_return, (unsigned char**)(void*)&desktop) != Success) return 0;
60 ret = desktop[0];
61 XFree(desktop);
63 return ret;
67 GArray * display_get_windows(struct display * display, long desktop) {
68 Atom actual_type_return;
69 int actual_format_return = 0;
70 unsigned long nitems_return = 0;
71 unsigned long bytes_after_return = 0;
72 unsigned long count;
73 Window * windows = NULL;
75 GArray * array;
77 if (XGetWindowProperty(display->display, display->root, XInternAtom(display->display, "_NET_CLIENT_LIST", False), 0, 0x7fffffff, False, XA_WINDOW, &actual_type_return, &actual_format_return, &nitems_return, &bytes_after_return, (unsigned char **)&windows) != Success) {
78 return NULL;
81 array = g_array_new(FALSE, FALSE, sizeof(Window));
82 for (count = 0; count < nitems_return; count++) {
83 long w_desktop = window_get_desktop(display, windows[count]);
84 if (w_desktop == desktop || w_desktop == ULONG_MAX) {
85 g_array_append_val(array, windows[count]);
89 XFree(windows);
91 return array;
94 void window_get_position(struct display * display, Window window, int position[2]) {
96 Window child;
97 XTranslateCoordinates(display->display, window, display->root, 0, 0, position + 0, position + 1, &child);
101 gint sort(gconstpointer a, gconstpointer b, gpointer data) {
102 int pos_a[2];
103 int pos_b[2];
105 gint result;
107 window_get_position((struct display*)data, *(Window*)a, pos_a);
108 window_get_position((struct display*)data, *(Window*)b, pos_b);
110 if ((result = pos_a[1] - pos_b[1])) return result;
112 return pos_a[0] - pos_b[0];
115 void window_activate(struct display * display, Window window) {
116 XEvent event;
117 long mask = SubstructureRedirectMask | SubstructureNotifyMask;
119 event.xclient.type = ClientMessage;
120 event.xclient.serial = 0;
121 event.xclient.send_event = True;
122 event.xclient.display = display->display;
123 event.xclient.window = window;
124 event.xclient.message_type = XInternAtom(display->display, "_NET_ACTIVE_WINDOW", False);
126 event.xclient.format = 32;
127 event.xclient.data.l[0] = 2;
128 event.xclient.data.l[1] = CurrentTime;
129 event.xclient.data.l[2] = 0;
130 event.xclient.data.l[3] = 0;
131 event.xclient.data.l[4] = 0;
133 XSendEvent(display->display, display->root, False, mask, &event);
136 int main(int argc, char ** argv) {
137 struct display * display;
138 GArray * windows;
139 long desktop;
141 if (argc < 2) {
142 fprintf(stderr, "Give me a window number to activate.\n");
143 fprintf(stderr, "Window numbers are integers >= 0.\n");
144 return 1;
147 display = display_open(NULL);
149 desktop = display_get_current_desktop(display);
150 windows = display_get_windows(display, desktop);
152 g_array_sort_with_data(windows, sort, (gpointer)display);
154 window_activate(display, g_array_index(windows, Window, atoi(argv[1])));
155 XFlush(display->display);
157 display_close(display);
158 g_array_free(windows, TRUE);
160 return 0;