int get_window_desktop(Window win) { int desktop = get_property32(win, server.atom._NET_WM_DESKTOP, XA_CARDINAL); if (desktop == ALL_DESKTOPS) return desktop; if (!server.viewports) return CLAMP(desktop, 0, server.num_desktops - 1); int x, y, w, h; get_window_coordinates(win, &x, &y, &w, &h); desktop = get_current_desktop(); // Window coordinates are relative to the current viewport, make them absolute x += server.viewports[desktop].x; y += server.viewports[desktop].y; if (x < 0 || y < 0) { int num_results; long *x_screen_size = server_get_property(server.root_win, server.atom._NET_DESKTOP_GEOMETRY, XA_CARDINAL, &num_results); if (!x_screen_size) return 0; int x_screen_width = x_screen_size[0]; int x_screen_height = x_screen_size[1]; XFree(x_screen_size); // Wrap if (x < 0) x += x_screen_width; if (y < 0) y += x_screen_height; } int best_match = -1; int match_right = 0; int match_bottom = 0; // There is an ambiguity when a window is right on the edge between viewports. // In that case, prefer the viewports which is on the right and bottom of the window's top-left corner. for (int i = 0; i < server.num_desktops; i++) { if (x >= server.viewports[i].x && x <= (server.viewports[i].x + server.viewports[i].width) && y >= server.viewports[i].y && y <= (server.viewports[i].y + server.viewports[i].height)) { int current_right = x < (server.viewports[i].x + server.viewports[i].width); int current_bottom = y < (server.viewports[i].y + server.viewports[i].height); if (best_match < 0 || (!match_right && current_right) || (!match_bottom && current_bottom)) { best_match = i; } } } if (best_match < 0) best_match = 0; // fprintf(stderr, "window %lx %s : viewport %d, (%d, %d)\n", win, get_task(win) ? get_task(win)->title : "??", // best_match+1, x, y); return best_match; }
void server_get_number_of_desktops() { if (server.viewports) { free(server.viewports); server.viewports = NULL; } server.num_desktops = get_property32(server.root_win, server.atom._NET_NUMBER_OF_DESKTOPS, XA_CARDINAL); if (server.num_desktops > 1) return; int num_results; long *work_area_size = server_get_property(server.root_win, server.atom._NET_WORKAREA, XA_CARDINAL, &num_results); if (!work_area_size) return; int work_area_width = work_area_size[0] + work_area_size[2]; int work_area_height = work_area_size[1] + work_area_size[3]; XFree(work_area_size); long *x_screen_size = server_get_property(server.root_win, server.atom._NET_DESKTOP_GEOMETRY, XA_CARDINAL, &num_results); if (!x_screen_size) return; int x_screen_width = x_screen_size[0]; int x_screen_height = x_screen_size[1]; XFree(x_screen_size); int num_viewports = MAX(x_screen_width / work_area_width, 1) * MAX(x_screen_height / work_area_height, 1); if (num_viewports <= 1) { server.num_desktops = 1; return; } server.viewports = calloc(num_viewports, sizeof(Viewport)); int k = 0; for (int i = 0; i < MAX(x_screen_height / work_area_height, 1); i++) { for (int j = 0; j < MAX(x_screen_width / work_area_width, 1); j++) { server.viewports[k].x = j * work_area_width; server.viewports[k].y = i * work_area_height; server.viewports[k].width = work_area_width; server.viewports[k].height = work_area_height; k++; } } server.num_desktops = num_viewports; }
int get_current_desktop() { if (!server.viewports) { return MAX(0, MIN(server.num_desktops - 1, get_property32(server.root_win, server.atom._NET_CURRENT_DESKTOP, XA_CARDINAL))); } int num_results; long *work_area_size = server_get_property(server.root_win, server.atom._NET_WORKAREA, XA_CARDINAL, &num_results); if (!work_area_size) return 0; int work_area_width = work_area_size[0] + work_area_size[2]; int work_area_height = work_area_size[1] + work_area_size[3]; XFree(work_area_size); if (work_area_width <= 0 || work_area_height <= 0) return 0; long *viewport = server_get_property(server.root_win, server.atom._NET_DESKTOP_VIEWPORT, XA_CARDINAL, &num_results); if (!viewport) return 0; int viewport_x = viewport[0]; int viewport_y = viewport[1]; XFree(viewport); long *x_screen_size = server_get_property(server.root_win, server.atom._NET_DESKTOP_GEOMETRY, XA_CARDINAL, &num_results); if (!x_screen_size) return 0; int x_screen_width = x_screen_size[0]; XFree(x_screen_size); int ncols = x_screen_width / work_area_width; // fprintf(stderr, "\n"); // fprintf(stderr, "Work area size: %d x %d\n", work_area_width, work_area_height); // fprintf(stderr, "Viewport pos: %d x %d\n", viewport_x, viewport_y); // fprintf(stderr, "Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x / work_area_width); int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width; return MAX(0, MIN(server.num_desktops - 1, result)); }
gboolean window_is_active(Window win) { return (win == get_property32(server.root_win, server.atom._NET_ACTIVE_WINDOW, XA_WINDOW)); }
Window get_active_window() { return get_property32(server.root_win, server.atom._NET_ACTIVE_WINDOW, XA_WINDOW); }
int server_get_current_desktop () { return get_property32(server.root_win, server.atom._NET_CURRENT_DESKTOP, XA_CARDINAL); }
int server_get_number_of_desktop () { return get_property32(server.root_win, server.atom._NET_NUMBER_OF_DESKTOPS, XA_CARDINAL); }
int window_get_desktop (Window win) { return get_property32(win, server.atom._NET_WM_DESKTOP, XA_CARDINAL); }