Ejemplo n.º 1
0
void transfer_node(monitor_t *ms, desktop_t *ds, monitor_t *md, desktop_t *dd, node_t *n)
{
    if (n == NULL || ds == NULL || dd == NULL || ms == NULL || md == NULL || (ms == md && dd == ds))
        return;

    PRINTF("transfer node %X\n", n->client->window);

    unlink_node(ds, n);
    insert_node(md, dd, n);
    ewmh_set_wm_desktop(n, dd);

    if (ds == ms->desk && dd != md->desk) {
        window_hide(n->client->window);
    }

    fit_monitor(md, n->client);

    if (n->client->fullscreen)
        window_move_resize(n->client->window, md->rectangle.x, md->rectangle.y, md->rectangle.width, md->rectangle.height);

    if (ds != ms->desk && dd == md->desk) {
        window_show(n->client->window);
        focus_node(md, dd, n, true);
    } else {
        focus_node(md, dd, n, false);
    }

    if (ds == ms->desk || dd == md->desk)
        update_current();
}
Ejemplo n.º 2
0
void client_message(xcb_generic_event_t *evt)
{
	xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;

	if (e->type == ewmh->_NET_CURRENT_DESKTOP) {
		coordinates_t loc;
		if (ewmh_locate_desktop(e->data.data32[0], &loc)) {
			focus_node(loc.monitor, loc.desktop, loc.desktop->focus);
		}
		return;
	}

	coordinates_t loc;
	if (!locate_window(e->window, &loc)) {
		return;
	}

	if (e->type == ewmh->_NET_WM_STATE) {
		handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[1], e->data.data32[0]);
		handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[2], e->data.data32[0]);
	} else if (e->type == ewmh->_NET_ACTIVE_WINDOW) {
		if ((ignore_ewmh_focus && e->data.data32[0] == XCB_EWMH_CLIENT_SOURCE_TYPE_NORMAL) ||
		    loc.node == mon->desk->focus) {
			return;
		}
		focus_node(loc.monitor, loc.desktop, loc.node);
	} else if (e->type == ewmh->_NET_WM_DESKTOP) {
		coordinates_t dloc;
		if (ewmh_locate_desktop(e->data.data32[0], &dloc)) {
			transfer_node(loc.monitor, loc.desktop, loc.node, dloc.monitor, dloc.desktop, dloc.desktop->focus);
		}
	} else if (e->type == ewmh->_NET_CLOSE_WINDOW) {
		window_close(loc.node);
	}
}
Ejemplo n.º 3
0
Archivo: tag.c Proyecto: mztriz/bspwm
void set_visibility(monitor_t *m, desktop_t *d, node_t *n, bool visible)
{
    PRINTF("set visibilty %X: %s\n", n->client->window, BOOLSTR(visible));

    if (!n->client->floating) {
        n->vacant = !visible;
        update_vacant_state(n->parent);
        if (visible)
            rotate_brother(n);
        else
            unrotate_brother(n);
    }
    if (visible) {
        if (m->desk == d)
            window_show(n->client->window);
        if (d->focus == NULL) {
            if (mon->desk == d)
                focus_node(m, d, n);
            else
                pseudo_focus(d, n);
        }
    } else {
        if (m->desk == d || n->client->sticky)
            window_hide(n->client->window);
        if (d->focus == n) {
            node_t *f = history_get_node(d, n);
            if (f == NULL)
                f = closest_visible(d, n);
            if (mon->desk == d)
                focus_node(m, d, f);
            else
                pseudo_focus(d, f);
        }
    }
}
Ejemplo n.º 4
0
bool grab_pointer(pointer_action_t pac)
{
	xcb_window_t win = XCB_NONE;
	xcb_point_t pos;

	query_pointer(&win, &pos);

	coordinates_t loc;

	if (!locate_window(win, &loc)) {
		if (pac == ACTION_FOCUS) {
			monitor_t *m = monitor_from_point(pos);
			if (m != NULL && m != mon && (win == XCB_NONE || win == m->root)) {
				focus_node(m, m->desk, m->desk->focus);
				return true;
			}
		}
		return false;
	}

	if (pac == ACTION_FOCUS) {
		if (loc.node != mon->desk->focus) {
			focus_node(loc.monitor, loc.desktop, loc.node);
			return true;
		} else if (focus_follows_pointer) {
			stack(loc.desktop, loc.node, true);
		}
		return false;
	}

	if (loc.node->client->state == STATE_FULLSCREEN) {
		return true;
	}

	xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(dpy, xcb_grab_pointer(dpy, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME), NULL);

	if (reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) {
		free(reply);
		return true;
	}
	free(reply);

	if (pac == ACTION_MOVE) {
		put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move begin\n", loc.monitor->id, loc.desktop->id, loc.node->id);
	} else if (pac == ACTION_RESIZE_CORNER) {
		put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_corner begin\n", loc.monitor->id, loc.desktop->id, loc.node->id);
	} else if (pac == ACTION_RESIZE_SIDE) {
		put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_side begin\n", loc.monitor->id, loc.desktop->id, loc.node->id);
	}

	track_pointer(loc, pac, pos);

	return true;
}
Ejemplo n.º 5
0
bool transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
{
	if (ms == NULL || md == NULL || d == NULL || ms == md) {
		return false;
	}

	bool was_active = (d == ms->desk);

	unlink_desktop(ms, d);

	if (md->desk != NULL) {
		hide_desktop(d);
	}

	insert_desktop(md, d);
	history_transfer_desktop(md, d);

	if (was_active) {
		if (mon == ms) {
			focus_node(ms, NULL, NULL);
		} else {
			activate_node(ms, NULL, NULL);
		}
	}

	if (ms->sticky_count > 0 && was_active) {
		sticky_still = false;
		transfer_sticky_nodes(ms, d, ms->desk, d->root);
		sticky_still = true;
	}

	adapt_geometry(&ms->rectangle, &md->rectangle, d->root);
	arrange(md, d);

	if (md->desk == d) {
		if (mon == md) {
			focus_node(md, d, d->focus);
		} else {
			activate_node(md, d, d->focus);
		}
	}

	ewmh_update_wm_desktops();
	ewmh_update_desktop_names();
	ewmh_update_current_desktop();

	put_status(SBSC_MASK_DESKTOP_TRANSFER, "desktop_transfer 0x%08X 0x%08X 0x%08X\n", ms->id, d->id, md->id);
	put_status(SBSC_MASK_REPORT);

	return true;
}
Ejemplo n.º 6
0
void circulate_leaves(monitor_t *m, desktop_t *d, circulate_dir_t dir) {
    if (d == NULL || d->root == NULL || is_leaf(d->root))
        return;
    node_t *par = d->focus->parent;
    bool focus_first_child = is_first_child(d->focus);
    if (dir == CIRCULATE_FORWARD)
        for (node_t *s = second_extrema(d->root), *f = prev_leaf(s); f != NULL; s = prev_leaf(f), f = prev_leaf(s))
            swap_nodes(f, s);
    else
        for (node_t *f = first_extrema(d->root), *s = next_leaf(f); s != NULL; f = next_leaf(s), s = next_leaf(f))
            swap_nodes(f, s);
    if (focus_first_child)
        focus_node(m, d, par->first_child, true);
    else
        focus_node(m, d, par->second_child, true);
}
Ejemplo n.º 7
0
void motion_notify(xcb_generic_event_t *evt)
{
	PUTS("motion notify");

	xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt;

	int dtime = e->time - last_motion_time;
	if (dtime > 1000) {
		last_motion_time = e->time;
		last_motion_x = e->event_x;
		last_motion_y = e->event_y;
		return;
	}

	int mdist = abs(e->event_x - last_motion_x) + abs(e->event_y - last_motion_y);
	if (mdist < 10)
		return;

	disable_motion_recorder();

	xcb_window_t win = XCB_NONE;
	xcb_point_t pt = {e->root_x, e->root_y};
	query_pointer(&win, NULL);

	bool backup = pointer_follows_monitor;
	auto_raise = false;
	pointer_follows_monitor = false;
	if (!window_focus(win)) {
		monitor_t *m = monitor_from_point(pt);
		if (m != NULL && m != mon)
			focus_node(m, m->desk, m->desk->focus);
	}
	pointer_follows_monitor = backup;
	auto_raise = true;
}
Ejemplo n.º 8
0
void enter_notify(xcb_generic_event_t *evt)
{
	xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt;
	xcb_window_t win = e->event;

	PRINTF("enter notify %X %d %d\n", win, e->mode, e->detail);

	if (e->mode != XCB_NOTIFY_MODE_NORMAL ||
	    (mon->desk->focus != NULL &&
	     mon->desk->focus->client->window == win))
		return;

	bool pfm_backup = pointer_follows_monitor;
	bool pff_backup = pointer_follows_focus;
	auto_raise = false;
	pointer_follows_monitor = false;
	pointer_follows_focus = false;
	if (!window_focus(win)) {
		xcb_point_t pt = {e->root_x, e->root_y};
		monitor_t *m = monitor_from_point(pt);
		if (m != NULL && m != mon) {
			focus_node(m, m->desk, m->desk->focus);
		}
	}
	pointer_follows_monitor = pfm_backup;
	pointer_follows_focus = pff_backup;
	auto_raise = true;
}
Ejemplo n.º 9
0
void update_current(void)
{
    if (mon->desk->focus == NULL)
        ewmh_update_active_window();
    else
        focus_node(mon, mon->desk, mon->desk->focus, true);
    put_status();
}
Ejemplo n.º 10
0
void motion_notify(xcb_generic_event_t *evt)
{
	xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt;

	PRINTF("motion notify %X %i %i\n", e->event, e->root_x, e->root_y);

	int dtime = e->time - last_motion_time;
	if (dtime > 1000) {
		last_motion_time = e->time;
		last_motion_x = e->event_x;
		last_motion_y = e->event_y;
		return;
	}

	int mdist = abs(e->event_x - last_motion_x) + abs(e->event_y - last_motion_y);
	if (mdist < 10) {
		return;
	}

	xcb_window_t win = XCB_NONE;
	xcb_point_t pt = {e->root_x, e->root_y};
	query_pointer(&win, NULL);

	bool pfm_backup = pointer_follows_monitor;
	bool pff_backup = pointer_follows_focus;
	auto_raise = false;
	pointer_follows_monitor = false;
	pointer_follows_focus = false;
	coordinates_t loc;
	if (locate_window(win, &loc)) {
		if (loc.node != mon->desk->focus) {
			focus_node(loc.monitor, loc.desktop, loc.node);
		}
	} else {
		monitor_t *m = monitor_from_point(pt);
		if (m != NULL && m != mon) {
			focus_node(m, m->desk, m->desk->focus);
		}
	}
	pointer_follows_monitor = pfm_backup;
	pointer_follows_focus = pff_backup;
	auto_raise = true;

	disable_motion_recorder();
}
Ejemplo n.º 11
0
void client_message(xcb_generic_event_t *evt)
{
	xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;

	PRINTF("client message %X %u\n", e->window, e->type);

	if (e->type == ewmh->_NET_CURRENT_DESKTOP) {
		coordinates_t loc;
		if (ewmh_locate_desktop(e->data.data32[0], &loc))
			focus_node(loc.monitor, loc.desktop, loc.desktop->focus);
		return;
	}

	coordinates_t loc;
	if (!locate_window(e->window, &loc))
		return;

	if (e->type == ewmh->_NET_WM_STATE) {
		handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[1], e->data.data32[0]);
		handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[2], e->data.data32[0]);
	} else if (e->type == ewmh->_NET_ACTIVE_WINDOW) {
		if ((ignore_ewmh_focus && e->data.data32[0] == XCB_EWMH_CLIENT_SOURCE_TYPE_NORMAL) ||
		    loc.node == mon->desk->focus)
			return;
		if (loc.desktop->focus->client->fullscreen && loc.desktop->focus != loc.node) {
			set_fullscreen(loc.desktop->focus, false);
			arrange(loc.monitor, loc.desktop);
		}
		focus_node(loc.monitor, loc.desktop, loc.node);
	} else if (e->type == ewmh->_NET_WM_DESKTOP) {
		coordinates_t dloc;
		if (ewmh_locate_desktop(e->data.data32[0], &dloc))
			transfer_node(loc.monitor, loc.desktop, loc.node, dloc.monitor, dloc.desktop, dloc.desktop->focus);
	} else if (e->type == ewmh->_NET_CLOSE_WINDOW) {
		window_close(loc.node);
	}
}
Ejemplo n.º 12
0
void select_monitor(monitor_t *m)
{
    if (m == NULL || mon == m)
        return;

    PRINTF("select monitor %s\n", m->name);

    focus_node(m, m->desk, m->desk->focus, true);

    last_mon = mon;
    mon = m;

    ewmh_update_current_desktop();
    put_status();
}
Ejemplo n.º 13
0
Archivo: monitor.c Proyecto: dj95/bspwm
void remove_monitor(monitor_t *m)
{
	put_status(SBSC_MASK_MONITOR_REMOVE, "monitor_remove 0x%08X\n", m->id);

	while (m->desk_head != NULL) {
		remove_desktop(m, m->desk_head);
	}

	unlink_monitor(m);
	xcb_destroy_window(dpy, m->root);
	free(m);

	if (mon == NULL) {
		focus_node(NULL, NULL, NULL);
	}

	put_status(SBSC_MASK_REPORT);
}
Ejemplo n.º 14
0
void nearest_leaf(monitor_t *m, desktop_t *d, node_t *n, nearest_arg_t dir, skip_client_t skip)
{
    if (n == NULL)
        return;

    PUTS("nearest leaf");

    node_t *x = NULL;

    for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f))
        if (skip == CLIENT_SKIP_NONE || (skip == CLIENT_SKIP_TILED && !is_tiled(f->client)) || (skip == CLIENT_SKIP_FLOATING && is_tiled(f->client))
                || (skip == CLIENT_SKIP_CLASS_DIFFER && strcmp(f->client->class_name, n->client->class_name) == 0)
                || (skip == CLIENT_SKIP_CLASS_EQUAL && strcmp(f->client->class_name, n->client->class_name) != 0))
            if ((dir == NEAREST_OLDER
                        && (f->client->uid < n->client->uid)
                        && (x == NULL || f->client->uid > x->client->uid))
                    || (dir == NEAREST_NEWER
                        && (f->client->uid > n->client->uid)
                        && (x == NULL || f->client->uid < x->client->uid)))
                x = f;

    focus_node(m, d, x, true);
}
Ejemplo n.º 15
0
void remove_desktop(monitor_t *m, desktop_t *d)
{
	put_status(SBSC_MASK_DESKTOP_REMOVE, "desktop_remove 0x%08X 0x%08X\n", m->id, d->id);

	remove_node(m, d, d->root);
	unlink_desktop(m, d);
	history_remove(d, NULL, false);
	free(d);

	ewmh_update_current_desktop();
	ewmh_update_number_of_desktops();
	ewmh_update_desktop_names();

	if (mon != NULL && m->desk == NULL) {
		if (m == mon) {
			focus_node(m, NULL, NULL);
		} else {
			activate_node(m, NULL, NULL);
		}
	}

	put_status(SBSC_MASK_REPORT);
}
Ejemplo n.º 16
0
void cycle_leaf(monitor_t *m, desktop_t *d, node_t *n, cycle_dir_t dir, skip_client_t skip)
{
    if (n == NULL)
        return;

    PUTS("cycle leaf");

    node_t *f = (dir == CYCLE_PREV ? prev_leaf(n) : next_leaf(n));
    if (f == NULL)
        f = (dir == CYCLE_PREV ? second_extrema(d->root) : first_extrema(d->root));

    while (f != n) {
        bool tiled = is_tiled(f->client);
        if (skip == CLIENT_SKIP_NONE || (skip == CLIENT_SKIP_TILED && !tiled) || (skip == CLIENT_SKIP_FLOATING && tiled)
                || (skip == CLIENT_SKIP_CLASS_DIFFER && strcmp(f->client->class_name, n->client->class_name) == 0)
                || (skip == CLIENT_SKIP_CLASS_EQUAL && strcmp(f->client->class_name, n->client->class_name) != 0)) {
            focus_node(m, d, f, true);
            return;
        }
        f = (dir == CYCLE_PREV ? prev_leaf(f) : next_leaf(f));
        if (f == NULL)
            f = (dir == CYCLE_PREV ? second_extrema(d->root) : first_extrema(d->root));
    }
}
Ejemplo n.º 17
0
Archivo: window.c Proyecto: nfnty/bspwm
bool move_client(coordinates_t *loc, int dx, int dy)
{
	node_t *n = loc->node;

	if (n == NULL || n->client == NULL) {
		return false;
	}

	monitor_t *pm = NULL;

	if (IS_TILED(n->client)) {
		if (!grabbing) {
			return false;
		}
		xcb_window_t pwin = XCB_NONE;
		query_pointer(&pwin, NULL);
		if (pwin == n->id) {
			return false;
		}
		coordinates_t dst;
		bool is_managed = (pwin != XCB_NONE && locate_window(pwin, &dst));
		if (is_managed && dst.monitor == loc->monitor && IS_TILED(dst.node->client)) {
			swap_nodes(loc->monitor, loc->desktop, n, loc->monitor, loc->desktop, dst.node);
			return true;
		} else {
			if (is_managed && dst.monitor == loc->monitor) {
				return false;
			} else {
				xcb_point_t pt = {0, 0};
				query_pointer(NULL, &pt);
				pm = monitor_from_point(pt);
			}
		}
	} else {
		client_t *c = n->client;
		xcb_rectangle_t rect = c->floating_rectangle;
		int16_t x = rect.x + dx;
		int16_t y = rect.y + dy;

		if (focus_follows_pointer) {
			listen_enter_notify(loc->desktop->root, false);
		}

		window_move(n->id, x, y);

		if (focus_follows_pointer) {
			listen_enter_notify(loc->desktop->root, true);
		}

		c->floating_rectangle.x = x;
		c->floating_rectangle.y = y;
		if (!grabbing) {
			put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc->monitor->id, loc->desktop->id, loc->node->id, rect.width, rect.height, x, y);
		}
		pm = monitor_from_client(c);
	}

	if (pm == NULL || pm == loc->monitor) {
		return true;
	}

	bool focused = (n == mon->desk->focus);
	transfer_node(loc->monitor, loc->desktop, n, pm, pm->desk, pm->desk->focus);
	loc->monitor = pm;
	loc->desktop = pm->desk;
	if (focused) {
		focus_node(pm, pm->desk, n);
	}

	return true;
}
Ejemplo n.º 18
0
void grab_pointer(pointer_action_t pac)
{
    PRINTF("grab pointer %u\n", pac);

    xcb_window_t win = XCB_NONE;
    xcb_point_t pos;

    query_pointer(&win, &pos);

    coordinates_t loc;
    if (locate_window(win, &loc)) {
        client_t *c = NULL;
        frozen_pointer->position = pos;
        frozen_pointer->action = pac;
        c = loc.node->client;
        frozen_pointer->monitor = loc.monitor;
        frozen_pointer->desktop = loc.desktop;
        frozen_pointer->node = loc.node;
        frozen_pointer->client = c;
        frozen_pointer->window = c->window;
        frozen_pointer->horizontal_fence = NULL;
        frozen_pointer->vertical_fence = NULL;

        switch (pac)  {
            case ACTION_FOCUS:
                if (loc.node != mon->desk->focus) {
                    bool backup = pointer_follows_monitor;
                    pointer_follows_monitor = false;
                    focus_node(loc.monitor, loc.desktop, loc.node);
                    pointer_follows_monitor = backup;
                } else if (focus_follows_pointer) {
                    stack(loc.node, STACK_ABOVE);
                }
                frozen_pointer->action = ACTION_NONE;
                break;
            case ACTION_MOVE:
            case ACTION_RESIZE_SIDE:
            case ACTION_RESIZE_CORNER:
                if (is_tiled(c)) {
                    frozen_pointer->rectangle = c->tiled_rectangle;
                    frozen_pointer->is_tiled = true;
                } else if (is_floating(c)) {
                    frozen_pointer->rectangle = c->floating_rectangle;
                    frozen_pointer->is_tiled = false;
                } else {
                    frozen_pointer->action = ACTION_NONE;
                    return;
                }
                if (pac == ACTION_RESIZE_SIDE) {
                    float W = frozen_pointer->rectangle.width;
                    float H = frozen_pointer->rectangle.height;
                    float ratio = W / H;
                    float x = pos.x - frozen_pointer->rectangle.x;
                    float y = pos.y - frozen_pointer->rectangle.y;
                    float diag_a = ratio * y;
                    float diag_b = W - diag_a;
                    if (x < diag_a) {
                        if (x < diag_b)
                            frozen_pointer->side = SIDE_LEFT;
                        else
                            frozen_pointer->side = SIDE_BOTTOM;
                    } else {
                        if (x < diag_b)
                            frozen_pointer->side = SIDE_TOP;
                        else
                            frozen_pointer->side = SIDE_RIGHT;
                    }
                } else if (pac == ACTION_RESIZE_CORNER) {
                    int16_t mid_x = frozen_pointer->rectangle.x + (frozen_pointer->rectangle.width / 2);
                    int16_t mid_y = frozen_pointer->rectangle.y + (frozen_pointer->rectangle.height / 2);
                    if (pos.x > mid_x) {
                        if (pos.y > mid_y)
                            frozen_pointer->corner = CORNER_BOTTOM_RIGHT;
                        else
                            frozen_pointer->corner = CORNER_TOP_RIGHT;
                    } else {
                        if (pos.y > mid_y)
                            frozen_pointer->corner = CORNER_BOTTOM_LEFT;
                        else
                            frozen_pointer->corner = CORNER_TOP_LEFT;
                    }
                }
                if (frozen_pointer->is_tiled) {
                    if (pac == ACTION_RESIZE_SIDE) {
                        switch (frozen_pointer->side) {
                            case SIDE_TOP:
                                frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_UP);
                                break;
                            case SIDE_RIGHT:
                                frozen_pointer->vertical_fence = find_fence(loc.node, DIR_RIGHT);
                                break;
                            case SIDE_BOTTOM:
                                frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_DOWN);
                                break;
                            case SIDE_LEFT:
                                frozen_pointer->vertical_fence = find_fence(loc.node, DIR_LEFT);
                                break;
                        }
                    } else if (pac == ACTION_RESIZE_CORNER) {
                        switch (frozen_pointer->corner) {
                            case CORNER_TOP_LEFT:
                                frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_UP);
                                frozen_pointer->vertical_fence = find_fence(loc.node, DIR_LEFT);
                                break;
                            case CORNER_TOP_RIGHT:
                                frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_UP);
                                frozen_pointer->vertical_fence = find_fence(loc.node, DIR_RIGHT);
                                break;
                            case CORNER_BOTTOM_RIGHT:
                                frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_DOWN);
                                frozen_pointer->vertical_fence = find_fence(loc.node, DIR_RIGHT);
                                break;
                            case CORNER_BOTTOM_LEFT:
                                frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_DOWN);
                                frozen_pointer->vertical_fence = find_fence(loc.node, DIR_LEFT);
                                break;
                        }
                    }
                    if (frozen_pointer->horizontal_fence != NULL)
                        frozen_pointer->horizontal_ratio = frozen_pointer->horizontal_fence->split_ratio;
                    if (frozen_pointer->vertical_fence != NULL)
                        frozen_pointer->vertical_ratio = frozen_pointer->vertical_fence->split_ratio;
                }
                break;
            case ACTION_NONE:
                break;
        }
    } else {
        if (pac == ACTION_FOCUS) {
            monitor_t *m = monitor_from_point(pos);
            if (m != NULL && m != mon)
                focus_node(m, m->desk, m->desk->focus);
        }
        frozen_pointer->action = ACTION_NONE;
    }
}
Ejemplo n.º 19
0
void track_pointer(int root_x, int root_y)
{
    if (frozen_pointer->action == ACTION_NONE)
        return;

    int16_t delta_x, delta_y, x = 0, y = 0, w = 1, h = 1;
    uint16_t width, height;

    pointer_action_t pac = frozen_pointer->action;
    monitor_t *m = frozen_pointer->monitor;
    desktop_t *d = frozen_pointer->desktop;
    node_t *n = frozen_pointer->node;
    client_t *c = frozen_pointer->client;
    xcb_window_t win = frozen_pointer->window;
    xcb_rectangle_t rect = frozen_pointer->rectangle;
    node_t *vertical_fence = frozen_pointer->vertical_fence;
    node_t *horizontal_fence = frozen_pointer->horizontal_fence;

    delta_x = root_x - frozen_pointer->position.x;
    delta_y = root_y - frozen_pointer->position.y;

    switch (pac) {
        case ACTION_MOVE:
            if (frozen_pointer->is_tiled) {
                xcb_window_t pwin = XCB_NONE;
                query_pointer(&pwin, NULL);
                if (pwin == win)
                    return;
                coordinates_t loc;
                bool is_managed = (pwin == XCB_NONE ? false : locate_window(pwin, &loc));
                if (is_managed && is_tiled(loc.node->client) && loc.monitor == m) {
                    swap_nodes(m, d, n, m, d, loc.node);
                    arrange(m, d);
                } else {
                    if (is_managed && loc.monitor == m) {
                        return;
                    } else if (!is_managed) {
                        xcb_point_t pt = (xcb_point_t) {root_x, root_y};
                        monitor_t *pmon = monitor_from_point(pt);
                        if (pmon == NULL || pmon == m) {
                            return;
                        } else {
                            loc.monitor = pmon;
                            loc.desktop = pmon->desk;
                        }
                    }
                    bool focused = (n == mon->desk->focus);
                    transfer_node(m, d, n, loc.monitor, loc.desktop, loc.desktop->focus);
                    if (focused)
                        focus_node(loc.monitor, loc.desktop, n);
                    frozen_pointer->monitor = loc.monitor;
                    frozen_pointer->desktop = loc.desktop;
                }
            } else {
                x = rect.x + delta_x;
                y = rect.y + delta_y;
                window_move(win, x, y);
                c->floating_rectangle.x = x;
                c->floating_rectangle.y = y;
                xcb_point_t pt = (xcb_point_t) {root_x, root_y};
                monitor_t *pmon = monitor_from_point(pt);
                if (pmon == NULL || pmon == m)
                    return;
                bool focused = (n == mon->desk->focus);
                transfer_node(m, d, n, pmon, pmon->desk, pmon->desk->focus);
                if (focused)
                    focus_node(pmon, pmon->desk, n);
                frozen_pointer->monitor = pmon;
                frozen_pointer->desktop = pmon->desk;
            }
            break;
        case ACTION_RESIZE_SIDE:
        case ACTION_RESIZE_CORNER:
            if (frozen_pointer->is_tiled) {
                if (vertical_fence != NULL) {
                    double sr = frozen_pointer->vertical_ratio + (double) delta_x / vertical_fence->rectangle.width;
                    sr = MAX(0, sr);
                    sr = MIN(1, sr);
                    vertical_fence->split_ratio = sr;
                }
                if (horizontal_fence != NULL) {
                    double sr = frozen_pointer->horizontal_ratio + (double) delta_y / horizontal_fence->rectangle.height;
                    sr = MAX(0, sr);
                    sr = MIN(1, sr);
                    horizontal_fence->split_ratio = sr;
                }
                arrange(mon, mon->desk);
            } else {
                if (pac == ACTION_RESIZE_SIDE) {
                    switch (frozen_pointer->side) {
                        case SIDE_TOP:
                            x = rect.x;
                            y = rect.y + delta_y;
                            w = rect.width;
                            h = rect.height - delta_y;
                            break;
                        case SIDE_RIGHT:
                            x = rect.x;
                            y = rect.y;
                            w = rect.width + delta_x;
                            h = rect.height;
                            break;
                        case SIDE_BOTTOM:
                            x = rect.x;
                            y = rect.y;
                            w = rect.width;
                            h = rect.height + delta_y;
                            break;
                        case SIDE_LEFT:
                            x = rect.x + delta_x;
                            y = rect.y;
                            w = rect.width - delta_x;
                            h = rect.height;
                            break;
                    }
                    width = MAX(1, w);
                    height = MAX(1, h);
                    window_move_resize(win, x, y, width, height);
                    c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
                    window_draw_border(n, d->focus == n, mon == m);
                } else if (pac == ACTION_RESIZE_CORNER) {
                    switch (frozen_pointer->corner) {
                        case CORNER_TOP_LEFT:
                            x = rect.x + delta_x;
                            y = rect.y + delta_y;
                            w = rect.width - delta_x;
                            h = rect.height - delta_y;
                            break;
                        case CORNER_TOP_RIGHT:
                            x = rect.x;
                            y = rect.y + delta_y;
                            w = rect.width + delta_x;
                            h = rect.height - delta_y;
                            break;
                        case CORNER_BOTTOM_LEFT:
                            x = rect.x + delta_x;
                            y = rect.y;
                            w = rect.width - delta_x;
                            h = rect.height + delta_y;
                            break;
                        case CORNER_BOTTOM_RIGHT:
                            x = rect.x;
                            y = rect.y;
                            w = rect.width + delta_x;
                            h = rect.height + delta_y;
                            break;
                    }
                    width = MAX(1, w);
                    height = MAX(1, h);
                    window_move_resize(win, x, y, width, height);
                    c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
                    window_draw_border(n, d->focus == n, mon == m);
                }
            }
            break;
        case ACTION_FOCUS:
        case ACTION_NONE:
            break;
    }
}
Ejemplo n.º 20
0
void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
{
	monitor_t *m = mon;
	desktop_t *d = mon->desk;
	node_t *f = mon->desk->focus;

	parse_rule_consequence(fd, csq);

	if (!csq->manage) {
		free(csq->layer);
		free(csq->state);
		window_show(win);
		return;
	}

	if (csq->node_desc[0] != '\0') {
		coordinates_t ref = {m, d, f};
		coordinates_t trg = {NULL, NULL, NULL};
		if (node_from_desc(csq->node_desc, &ref, &trg)) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.node;
		}
	} else if (csq->desktop_desc[0] != '\0') {
		coordinates_t ref = {m, d, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (desktop_from_desc(csq->desktop_desc, &ref, &trg)) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.desktop->focus;
		}
	} else if (csq->monitor_desc[0] != '\0') {
		coordinates_t ref = {m, NULL, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (monitor_from_desc(csq->monitor_desc, &ref, &trg)) {
			m = trg.monitor;
			d = trg.monitor->desk;
			f = trg.monitor->desk->focus;
		}
	}

	if (csq->sticky) {
		m = mon;
		d = mon->desk;
		f = mon->desk->focus;
	}

	if (csq->split_dir[0] != '\0' && f != NULL) {
		direction_t dir;
		if (parse_direction(csq->split_dir, &dir)) {
			presel_dir(m, d, f, dir);
		}
	}

	if (csq->split_ratio != 0 && f != NULL) {
		presel_ratio(m, d, f, csq->split_ratio);
	}

	node_t *n = make_node(win);
	client_t *c = make_client();
	c->border_width = csq->border ? d->border_width : 0;
	n->client = c;
	initialize_client(n);
	update_floating_rectangle(n);

	if (c->floating_rectangle.x == 0 && c->floating_rectangle.y == 0) {
		csq->center = true;
	}

	c->min_width = csq->min_width;
	c->max_width = csq->max_width;
	c->min_height = csq->min_height;
	c->max_height = csq->max_height;

	monitor_t *mm = monitor_from_client(c);
	embrace_client(mm, c);
	adapt_geometry(&mm->rectangle, &m->rectangle, n);

	if (csq->center) {
		window_center(m, c);
	}

	snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name);
	snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name);

	f = insert_node(m, d, n, f);
	clients_count++;

	put_status(SBSC_MASK_NODE_MANAGE, "node_manage %s %s 0x%X 0x%X\n", m->name, d->name, win, f!=NULL?f->id:0);

	if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) {
		c->last_layer = c->layer = f->client->layer;
	}

	if (csq->layer != NULL) {
		c->last_layer = c->layer = *(csq->layer);
	}

	if (csq->state != NULL) {
		set_state(m, d, n, *(csq->state));
		c->last_state = c->state;
	}

	set_locked(m, d, n, csq->locked);
	set_sticky(m, d, n, csq->sticky);
	set_private(m, d, n, csq->private);

	arrange(m, d);

	bool give_focus = (csq->focus && (d == mon->desk || csq->follow));

	if (give_focus) {
		focus_node(m, d, n);
	} else if (csq->focus) {
		activate_node(m, d, n);
	} else {
		stack(d, n, false);
	}

	uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
	xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);

	if (d == m->desk) {
		window_show(n->id);
	} else {
		window_hide(n->id);
	}

	/* the same function is already called in `focus_node` but has no effects on unmapped windows */
	if (give_focus) {
		xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
	}

	ewmh_set_wm_desktop(n, d);
	ewmh_update_client_list(false);
	free(csq->layer);
	free(csq->state);
}
Ejemplo n.º 21
0
void grab_pointer(pointer_action_t pac)
{
	xcb_window_t win = XCB_NONE;
	xcb_point_t pos;

	query_pointer(&win, &pos);

	coordinates_t loc;
	if (locate_window(win, &loc)) {
		client_t *c = loc.node->client;

		frozen_pointer->position = pos;
		frozen_pointer->action = pac;
		frozen_pointer->monitor = loc.monitor;
		frozen_pointer->desktop = loc.desktop;
		frozen_pointer->node = loc.node;
		frozen_pointer->client = c;
		frozen_pointer->window = loc.node->id;
		frozen_pointer->horizontal_fence = NULL;
		frozen_pointer->vertical_fence = NULL;

		switch (pac)  {
			case ACTION_FOCUS:
				if (loc.node != mon->desk->focus) {
					bool backup = pointer_follows_monitor;
					pointer_follows_monitor = false;
					focus_node(loc.monitor, loc.desktop, loc.node);
					pointer_follows_monitor = backup;
				} else if (focus_follows_pointer) {
					stack(loc.desktop, loc.node, true);
				}
				frozen_pointer->action = ACTION_NONE;
				break;
			case ACTION_MOVE:
			case ACTION_RESIZE_SIDE:
			case ACTION_RESIZE_CORNER:
				if (IS_FLOATING(c)) {
					frozen_pointer->rectangle = c->floating_rectangle;
					frozen_pointer->is_tiled = false;
				} else if (IS_TILED(c)) {
					frozen_pointer->rectangle = c->tiled_rectangle;
					frozen_pointer->is_tiled = (pac == ACTION_MOVE || c->state != STATE_PSEUDO_TILED);
				} else {
					frozen_pointer->action = ACTION_NONE;
					return;
				}
				if (pac == ACTION_RESIZE_SIDE) {
					float W = frozen_pointer->rectangle.width;
					float H = frozen_pointer->rectangle.height;
					float ratio = W / H;
					float x = pos.x - frozen_pointer->rectangle.x;
					float y = pos.y - frozen_pointer->rectangle.y;
					float diag_a = ratio * y;
					float diag_b = W - diag_a;
					if (x < diag_a) {
						if (x < diag_b) {
							frozen_pointer->side = SIDE_LEFT;
						} else {
							frozen_pointer->side = SIDE_BOTTOM;
						}
					} else {
						if (x < diag_b) {
							frozen_pointer->side = SIDE_TOP;
						} else {
							frozen_pointer->side = SIDE_RIGHT;
						}
					}
				} else if (pac == ACTION_RESIZE_CORNER) {
					int16_t mid_x = frozen_pointer->rectangle.x + (frozen_pointer->rectangle.width / 2);
					int16_t mid_y = frozen_pointer->rectangle.y + (frozen_pointer->rectangle.height / 2);
					if (pos.x > mid_x) {
						if (pos.y > mid_y) {
							frozen_pointer->corner = CORNER_BOTTOM_RIGHT;
						} else {
							frozen_pointer->corner = CORNER_TOP_RIGHT;
						}
					} else {
						if (pos.y > mid_y) {
							frozen_pointer->corner = CORNER_BOTTOM_LEFT;
						} else {
							frozen_pointer->corner = CORNER_TOP_LEFT;
						}
					}
				}
				if (frozen_pointer->is_tiled) {
					if (pac == ACTION_RESIZE_SIDE) {
						switch (frozen_pointer->side) {
							case SIDE_TOP:
								frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_NORTH);
								break;
							case SIDE_RIGHT:
								frozen_pointer->vertical_fence = find_fence(loc.node, DIR_EAST);
								break;
							case SIDE_BOTTOM:
								frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_SOUTH);
								break;
							case SIDE_LEFT:
								frozen_pointer->vertical_fence = find_fence(loc.node, DIR_WEST);
								break;
						}
					} else if (pac == ACTION_RESIZE_CORNER) {
						switch (frozen_pointer->corner) {
							case CORNER_TOP_LEFT:
								frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_NORTH);
								frozen_pointer->vertical_fence = find_fence(loc.node, DIR_WEST);
								break;
							case CORNER_TOP_RIGHT:
								frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_NORTH);
								frozen_pointer->vertical_fence = find_fence(loc.node, DIR_EAST);
								break;
							case CORNER_BOTTOM_RIGHT:
								frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_SOUTH);
								frozen_pointer->vertical_fence = find_fence(loc.node, DIR_EAST);
								break;
							case CORNER_BOTTOM_LEFT:
								frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_SOUTH);
								frozen_pointer->vertical_fence = find_fence(loc.node, DIR_WEST);
								break;
						}
					}
					if (frozen_pointer->horizontal_fence != NULL) {
						frozen_pointer->horizontal_ratio = frozen_pointer->horizontal_fence->split_ratio;
					}
					if (frozen_pointer->vertical_fence != NULL) {
						frozen_pointer->vertical_ratio = frozen_pointer->vertical_fence->split_ratio;
					}
				}
				break;
			case ACTION_NONE:
				break;
		}
	} else {
		if (pac == ACTION_FOCUS) {
			monitor_t *m = monitor_from_point(pos);
			if (m != NULL && m != mon && (win == XCB_NONE || win == m->root)) {
				focus_node(m, m->desk, m->desk->focus);
			}
		}
		frozen_pointer->action = ACTION_NONE;
	}
}
Ejemplo n.º 22
0
bool swap_desktops(monitor_t *m1, desktop_t *d1, monitor_t *m2, desktop_t *d2)
{
	if (d1 == NULL || d2 == NULL || d1 == d2 ||
	    (m1->desk == d1 && m1->sticky_count > 0) ||
	    (m2->desk == d2 && m2->sticky_count > 0)) {
		return false;
	}

	put_status(SBSC_MASK_DESKTOP_SWAP, "desktop_swap 0x%08X 0x%08X 0x%08X 0x%08X\n", m1->id, d1->id, m2->id, d2->id);

	bool d1_focused = (m1->desk == d1);
	bool d2_focused = (m2->desk == d2);

	if (m1 != m2) {
		if (m1->desk == d1) {
			m1->desk = d2;
		}
		if (m1->desk_head == d1) {
			m1->desk_head = d2;
		}
		if (m1->desk_tail == d1) {
			m1->desk_tail = d2;
		}
		if (m2->desk == d2) {
			m2->desk = d1;
		}
		if (m2->desk_head == d2) {
			m2->desk_head = d1;
		}
		if (m2->desk_tail == d2) {
			m2->desk_tail = d1;
		}
	} else {
		if (m1->desk == d1) {
			m1->desk = d2;
		} else if (m1->desk == d2) {
			m1->desk = d1;
		}
		if (m1->desk_head == d1) {
			m1->desk_head = d2;
		} else if (m1->desk_head == d2) {
			m1->desk_head = d1;
		}
		if (m1->desk_tail == d1) {
			m1->desk_tail = d2;
		} else if (m1->desk_tail == d2) {
			m1->desk_tail = d1;
		}
	}

	desktop_t *p1 = d1->prev;
	desktop_t *n1 = d1->next;
	desktop_t *p2 = d2->prev;
	desktop_t *n2 = d2->next;

	if (p1 != NULL && p1 != d2) {
		p1->next = d2;
	}
	if (n1 != NULL && n1 != d2) {
		n1->prev = d2;
	}
	if (p2 != NULL && p2 != d1) {
		p2->next = d1;
	}
	if (n2 != NULL && n2 != d1) {
		n2->prev = d1;
	}

	d1->prev = p2 == d1 ? d2 : p2;
	d1->next = n2 == d1 ? d2 : n2;
	d2->prev = p1 == d2 ? d1 : p1;
	d2->next = n1 == d2 ? d1 : n1;

	if (m1 != m2) {
		adapt_geometry(&m1->rectangle, &m2->rectangle, d1->root);
		adapt_geometry(&m2->rectangle, &m1->rectangle, d2->root);
		history_swap_desktops(m1, d1, m2, d2);
		arrange(m1, d2);
		arrange(m2, d1);
	}

	if (d1_focused && !d2_focused) {
		hide_desktop(d1);
		show_desktop(d2);
	} else if (!d1_focused && d2_focused) {
		show_desktop(d1);
		hide_desktop(d2);
	}

	if (d1 == mon->desk) {
		focus_node(m2, d1, d1->focus);
	} else if (d1 == m2->desk) {
		activate_node(m2, d1, d1->focus);
	}

	if (d2 == mon->desk) {
		focus_node(m1, d2, d2->focus);
	} else if (d2 == m1->desk) {
		activate_node(m1, d2, d2->focus);
	}

	ewmh_update_wm_desktops();
	ewmh_update_desktop_names();
	ewmh_update_current_desktop();

	put_status(SBSC_MASK_REPORT);

	return true;
}
Ejemplo n.º 23
0
Archivo: window.c Proyecto: nfnty/bspwm
void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
{
	monitor_t *m = mon;
	desktop_t *d = mon->desk;
	node_t *f = mon->desk->focus;

	parse_rule_consequence(fd, csq);

	if (!csq->manage) {
		free(csq->layer);
		free(csq->state);
		window_show(win);
		return;
	}

	if (csq->node_desc[0] != '\0') {
		coordinates_t ref = {m, d, f};
		coordinates_t trg = {NULL, NULL, NULL};
		if (node_from_desc(csq->node_desc, &ref, &trg) == SELECTOR_OK) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.node;
		}
	} else if (csq->desktop_desc[0] != '\0') {
		coordinates_t ref = {m, d, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (desktop_from_desc(csq->desktop_desc, &ref, &trg) == SELECTOR_OK) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.desktop->focus;
		}
	} else if (csq->monitor_desc[0] != '\0') {
		coordinates_t ref = {m, NULL, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (monitor_from_desc(csq->monitor_desc, &ref, &trg) == SELECTOR_OK) {
			m = trg.monitor;
			d = trg.monitor->desk;
			f = trg.monitor->desk->focus;
		}
	}

	if (csq->sticky) {
		m = mon;
		d = mon->desk;
		f = mon->desk->focus;
	}

	if (csq->split_dir[0] != '\0' && f != NULL) {
		direction_t dir;
		if (parse_direction(csq->split_dir, &dir)) {
			presel_dir(m, d, f, dir);
		}
	}

	if (csq->split_ratio != 0 && f != NULL) {
		presel_ratio(m, d, f, csq->split_ratio);
	}

	node_t *n = make_node(win);
	client_t *c = make_client();
	c->border_width = csq->border ? d->border_width : 0;
	n->client = c;
	initialize_client(n);
	initialize_floating_rectangle(n);

	if (c->floating_rectangle.x == 0 && c->floating_rectangle.y == 0) {
		csq->center = true;
	}

	monitor_t *mm = monitor_from_client(c);
	embrace_client(mm, c);
	adapt_geometry(&mm->rectangle, &m->rectangle, n);

	if (csq->center) {
		window_center(m, c);
	}

	snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name);
	snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name);

	f = insert_node(m, d, n, f);
	clients_count++;

	put_status(SBSC_MASK_NODE_MANAGE, "node_manage 0x%08X 0x%08X 0x%08X 0x%08X\n", m->id, d->id, win, f!=NULL?f->id:0);

	if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) {
		c->layer = f->client->layer;
	}

	if (csq->layer != NULL) {
		c->layer = *(csq->layer);
	}

	if (csq->state != NULL) {
		set_state(m, d, n, *(csq->state));
	}

	set_hidden(m, d, n, csq->hidden);
	set_sticky(m, d, n, csq->sticky);
	set_private(m, d, n, csq->private);
	set_locked(m, d, n, csq->locked);

	arrange(m, d);

	uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
	xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);

	if (d == m->desk) {
		show_node(d, n);
	} else {
		hide_node(d, n);
	}

	if (!csq->hidden && csq->focus) {
		if (d == mon->desk || csq->follow) {
			focus_node(m, d, n);
		} else {
			activate_node(m, d, n);
		}
	} else {
		stack(d, n, false);
	}

	ewmh_set_wm_desktop(n, d);
	ewmh_update_client_list(false);
	free(csq->layer);
	free(csq->state);
}