Example #1
0
static void
layout_fibonacci(int screen, int shape)
{
    int n = 0, i = 0;
    client_t *c;
    area_t geometry, area;
    geometry = area = screen_area_get(screen,
                                      &globalconf.screens[screen].wiboxes,
                                      &globalconf.screens[screen].padding,
                                      true);

    for(c = globalconf.clients; c; c = c->next)
        if(IS_TILED(c, screen))
            n++;
    for(c = globalconf.clients; c; c = c->next)
        if(IS_TILED(c, screen))
        {
            if((i % 2 && geometry.height / 2 > 2 * c->border)
               || (!(i % 2) && geometry.width / 2 > 2 * c->border))
            {
                if(i < n - 1)
                {
                    if(i % 2)
                        geometry.height /= 2;
                    else
                        geometry.width /= 2;
                    if((i % 4) == 2 && !shape)
                        geometry.x += geometry.width;
                    else if((i % 4) == 3 && !shape)
                        geometry.y += geometry.height;
                }
                if((i % 4) == 0)
                {
                    if(shape)
                        geometry.y += geometry.height;
                    else
                        geometry.y -= geometry.height;
                }
                else if((i % 4) == 1)
                    geometry.x += geometry.width;
                else if((i % 4) == 2)
                    geometry.y += geometry.height;
                else if((i % 4) == 3)
                {
                    if(shape)
                        geometry.x += geometry.width;
                    else
                        geometry.x -= geometry.width;
                }
                if(i == 0)
                    geometry.y = area.y;
                i++;
            }
            geometry.width -= 2 * c->border;
            geometry.height -= 2 * c->border;
            client_resize(c, geometry, c->honorsizehints);
            geometry.width += 2 * c->border;
            geometry.height += 2 * c->border;
        }
}
Example #2
0
void initialize_presel_feedback(node_t *n)
{
	if (n == NULL || n->presel == NULL || n->presel->feedback != XCB_NONE) {
		return;
	}

	xcb_window_t win = xcb_generate_id(dpy);
	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_SAVE_UNDER;
	uint32_t values[] = {get_color_pixel(presel_feedback_color), 1};
	xcb_create_window(dpy, XCB_COPY_FROM_PARENT, win, root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
			          XCB_COPY_FROM_PARENT, mask, values);

	xcb_icccm_set_wm_class(dpy, win, sizeof(PRESEL_FEEDBACK_IC), PRESEL_FEEDBACK_IC);
	stacking_list_t *s = stack_tail;
	while (s != NULL && !IS_TILED(s->node->client)) {
		s = s->prev;
	}
	if (s != NULL) {
		window_above(win, s->node->id);
	}
	n->presel->feedback = win;
}
Example #3
0
void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos)
{
	node_t *n = loc.node;
	resize_handle_t rh = get_handle(loc.node, pos, pac);

	uint16_t last_motion_x = pos.x, last_motion_y = pos.y;
	xcb_timestamp_t last_motion_time = 0;

	xcb_generic_event_t *evt = NULL;

	grabbing = true;
	grabbed_node = n;

	do {
		free(evt);
		while ((evt = xcb_wait_for_event(dpy)) == NULL) {
			xcb_flush(dpy);
		}
		uint8_t resp_type = XCB_EVENT_RESPONSE_TYPE(evt);
		if (resp_type == XCB_MOTION_NOTIFY) {
			xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t*) evt;
			uint32_t dtime = e->time - last_motion_time;
			if (dtime < pointer_motion_interval) {
				continue;
			}
			last_motion_time = e->time;
			int16_t dx = e->root_x - last_motion_x;
			int16_t dy = e->root_y - last_motion_y;
			if (pac == ACTION_MOVE) {
				move_client(&loc, dx, dy);
			} else {
				resize_client(&loc, rh, e->root_x, e->root_y, false);
			}
			last_motion_x = e->root_x;
			last_motion_y = e->root_y;
			xcb_flush(dpy);
		} else if (resp_type == XCB_BUTTON_RELEASE) {
			grabbing = false;
		} else {
			handle_event(evt);
		}
	} while (grabbing && grabbed_node != NULL);
	free(evt);

	xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME);

	if (grabbed_node == NULL) {
		grabbing = false;
		return;
	}

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

	xcb_rectangle_t r = get_rectangle(NULL, NULL, n);

	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, r.width, r.height, r.x, r.y);

	if ((pac == ACTION_MOVE && IS_TILED(n->client)) ||
	    ((pac == ACTION_RESIZE_CORNER || pac == ACTION_RESIZE_SIDE) &&
	     n->client->state == STATE_TILED)) {
		for (node_t *f = first_extrema(loc.desktop->root); f != NULL; f = next_leaf(f, loc.desktop->root)) {
			if (f == n || f->client == NULL || !IS_TILED(f->client)) {
				continue;
			}
			xcb_rectangle_t r = f->client->tiled_rectangle;
			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, f->id, r.width, r.height, r.x, r.y);
		}
	}
}
Example #4
0
int stack_level(client_t *c)
{
    int layer_level = (c->layer == LAYER_NORMAL ? 1 : (c->layer == LAYER_BELOW ? 0 : 2));
    int state_level = (IS_TILED(c) ? 0 : (IS_FLOATING(c) ? 2 : 1));
    return 3 * layer_level + state_level;
}
Example #5
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, 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_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;
	}
}
Example #6
0
File: window.c Project: 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;
}
Example #7
0
void
layout_magnifier(int screen)
{
    int n = 0;
    client_t *c, *focus;
    tag_t **curtags = tags_get_current(screen);
    area_t geometry, area = screen_area_get(screen,
                                            &globalconf.screens[screen].wiboxes,
                                            &globalconf.screens[screen].padding,
                                            true);

    focus = globalconf.screens[screen].client_focus;

    /* Find parent of this window, if it has one. */
    if (!IS_TILED(focus, screen) && focus && focus->transient_for)
        do {
            focus = focus->transient_for;
        } while (focus->transient_for != NULL);

    /* If focused window is not tiled, take the first one which is tiled. */
    if(!IS_TILED(focus, screen))
        for(focus = globalconf.clients; focus && !IS_TILED(focus, screen); focus = focus->next);

    /* No windows is tiled, nothing to do. */
    if(!focus)
        goto bailout;

    for(c = client_list_prev_cycle(&globalconf.clients, focus);
        c && c != focus;
        c = client_list_prev_cycle(&globalconf.clients, c))
        if(IS_TILED(c, screen) && c != focus)
            n++;

    if(n)
    {
        geometry.width = area.width * sqrt(curtags[0]->mwfact);
        geometry.height = area.height *  sqrt(curtags[0]->mwfact);
        geometry.x = area.x + (area.width - geometry.width) / 2;
        geometry.y = area.y + (area.height - geometry.height) / 2;
    }
    else
    {
       /* No other clients. */
        geometry = area;
        geometry.width -= 2 * focus->border;
        geometry.height -= 2 * focus->border;
    }
    client_resize(focus, geometry, focus->honorsizehints);
    client_raise(focus);

    /* bailout when there is only one window */
    if (!n)
	goto bailout;

    geometry.x = area.x;
    geometry.y = area.y;
    geometry.height = area.height / n;
    geometry.width = area.width;

    for(c = client_list_prev_cycle(&globalconf.clients, focus);
        c && c != focus;
        c = client_list_prev_cycle(&globalconf.clients, c))
        if(IS_TILED(c, screen) && c != focus)
        {
            geometry.height -= 2 * c->border;
            geometry.width -= 2 * c->border;
            client_resize(c, geometry, c->honorsizehints);
            geometry.height += 2 * c->border;
            geometry.width += 2 * c->border;
            geometry.y += geometry.height;
        }

bailout:
    p_delete(&curtags);
}