1 /* gcc -Wall -pedantic -o focus focus.c -lX11 `pkg-config --cflags --libs glib-2.0` -O2 -fno-strict-aliasing */
4 #include <glib.h> /* sorting, oh my */
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
);
22 void display_close(struct display
* display
) {
23 XCloseDisplay(display
->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;
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
) {
40 if (actual_type_return
!= XA_CARDINAL
|| nitems_return
== 0) {
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;
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;
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;
73 Window
* windows
= NULL
;
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
) {
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
]);
94 void window_get_position(struct display
* display
, Window window
, int position
[2]) {
97 XTranslateCoordinates(display
->display
, window
, display
->root
, 0, 0, position
+ 0, position
+ 1, &child
);
101 gint
sort(gconstpointer a
, gconstpointer b
, gpointer data
) {
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
) {
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
;
142 fprintf(stderr
, "Give me a window number to activate.\n");
143 fprintf(stderr
, "Window numbers are integers >= 0.\n");
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
);