Ejemplo n.º 1
0
Archivo: layout.c Proyecto: thuck/sway
void move_container_to(swayc_t* container, swayc_t* destination) {
	if (container == destination || swayc_is_parent_of(container, destination)) {
		return;
	}
	swayc_t *parent = remove_child(container);
	// Send to new destination
	if (container->is_floating) {
		swayc_t *ws = swayc_active_workspace_for(destination);
		add_floating(ws, container);

		// If the workspace only has one child after adding one, it
		// means that the workspace was just initialized.
		if (ws->children->length + ws->floating->length == 1) {
			ipc_event_workspace(NULL, ws, "init");
		}
	} else if (destination->type == C_WORKSPACE) {
		// reset container geometry
		container->width = container->height = 0;
		add_child(destination, container);

		// If the workspace only has one child after adding one, it
		// means that the workspace was just initialized.
		if (destination->children->length + destination->floating->length == 1) {
			ipc_event_workspace(NULL, destination, "init");
		}
	} else {
		// reset container geometry
		container->width = container->height = 0;
		add_sibling(destination, container);
	}
	// Destroy old container if we need to
	parent = destroy_container(parent);
	// Refocus
	swayc_t *op1 = swayc_parent_by_type(destination, C_OUTPUT);
	swayc_t *op2 = swayc_parent_by_type(parent, C_OUTPUT);
	set_focused_container(get_focused_view(op1));
	arrange_windows(op1, -1, -1);
	update_visibility(op1);
	if (op1 != op2) {
		set_focused_container(get_focused_view(op2));
		arrange_windows(op2, -1, -1);
		update_visibility(op2);
	}
}
Ejemplo n.º 2
0
static void handle_output_focused(wlc_handle output, bool focus) {
	swayc_t *c = get_swayc_for_handle(output, &root_container);
	// if for some reason this output doesnt exist, create it.
	if (!c) {
		handle_output_created(output);
	}
	if (focus) {
		set_focused_container(c);
	}
}
Ejemplo n.º 3
0
bool move_focus(enum movement_direction direction) {
	swayc_t *old_view = get_focused_container(&root_container);
	swayc_t *new_view = get_swayc_in_direction(old_view, direction);
	if (!new_view) {
		return false;
	} else if (direction == MOVE_PARENT) {
		return set_focused_container(new_view);
	} else if (config->mouse_warping) {
		swayc_t *old_op = old_view->type == C_OUTPUT ?
			old_view : swayc_parent_by_type(old_view, C_OUTPUT);
		swayc_t *focused = get_focused_view(new_view);
		if (set_focused_container(focused)) {
			if (old_op != swayc_active_output() && focused && focused->type == C_VIEW) {
				center_pointer_on(focused);
			}
			return true;
		}
	} else {
		return set_focused_container(get_focused_view(new_view));
	}
	return false;
}
Ejemplo n.º 4
0
Archivo: layout.c Proyecto: thuck/sway
void move_workspace_to(swayc_t* workspace, swayc_t* destination) {
	if (workspace == destination || swayc_is_parent_of(workspace, destination)) {
		return;
	}
	swayc_t *src_op = remove_child(workspace);
	// reset container geometry
	workspace->width = workspace->height = 0;
	add_child(destination, workspace);
	// Refocus destination (change to new workspace)
	set_focused_container(get_focused_view(workspace));
	arrange_windows(destination, -1, -1);
	update_visibility(destination);

	// make sure source output has a workspace
	if (src_op->children->length == 0) {
		char *ws_name = workspace_next_name(src_op->name);
		swayc_t *ws = new_workspace(src_op, ws_name);
		ws->is_focused = true;
		free(ws_name);
	}
	set_focused_container(get_focused_view(src_op));
	update_visibility(src_op);
}
Ejemplo n.º 5
0
bool workspace_switch(swayc_t *workspace) {
	if (!workspace) {
		return false;
	}
	swayc_t *active_ws = swayc_active_workspace();
	if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) {
		swayc_t *new_ws = workspace_by_name(prev_workspace_name);
		workspace = new_ws ? new_ws : workspace_create(prev_workspace_name);
	}

	if (!prev_workspace_name
			|| (strcmp(prev_workspace_name, active_ws->name)
				&& active_ws != workspace)) {
		free(prev_workspace_name);
		prev_workspace_name = malloc(strlen(active_ws->name)+1);
		strcpy(prev_workspace_name, active_ws->name);
	}

	// move sticky containers
	if (swayc_parent_by_type(active_ws, C_OUTPUT) == swayc_parent_by_type(workspace, C_OUTPUT)) {
		// don't change list while traversing it, use intermediate list instead
		list_t *stickies = create_list();
		for (int i = 0; i < active_ws->floating->length; i++) {
			swayc_t *cont = active_ws->floating->items[i];
			if (cont->sticky) {
				list_add(stickies, cont);
			}
		}
		for (int i = 0; i < stickies->length; i++) {
			swayc_t *cont = stickies->items[i];
			sway_log(L_DEBUG, "Moving sticky container %p to %p:%s",
					cont, workspace, workspace->name);
			swayc_t *parent = remove_child(cont);
			add_floating(workspace, cont);
			// Destroy old container if we need to
			destroy_container(parent);
		}
		list_free(stickies);
	}
	sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name);
	if (!set_focused_container(get_focused_view(workspace))) {
		return false;
	}
	swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT);
	arrange_backgrounds();
	arrange_windows(output, -1, -1);
	return true;
}
Ejemplo n.º 6
0
void workspace_switch(swayc_t *workspace) {
	if (!workspace) {
		return;
	}
	if (strcmp(prev_workspace_name, swayc_active_workspace()->name) != 0 && swayc_active_workspace() != workspace) {
		prev_workspace_name = malloc(strlen(swayc_active_workspace()->name) + 1);
		strcpy(prev_workspace_name, swayc_active_workspace()->name);
	} else if (config->auto_back_and_forth && swayc_active_workspace() == workspace && strlen(prev_workspace_name) != 0) {
		workspace = workspace_by_name(prev_workspace_name) ? workspace_by_name(prev_workspace_name) : workspace_create(prev_workspace_name);
		prev_workspace_name = malloc(strlen(swayc_active_workspace()->name) + 1);
		strcpy(prev_workspace_name, swayc_active_workspace()->name);
	}

	sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name);
	set_focused_container(get_focused_view(workspace));
	arrange_windows(workspace, -1, -1);
}
Ejemplo n.º 7
0
bool set_focused_container_for(swayc_t *a, swayc_t *c) {
	if (locked_container_focus || !c) {
		return false;
	}
	swayc_t *find = c;
	// Ensure that a is an ancestor of c
	while (find != a && (find = find->parent)) {
		if (find == &root_container) {
			return false;
		}
	}

	// Get workspace for c, get that workspaces current focused container.
	swayc_t *workspace = swayc_active_workspace_for(c);
	swayc_t *focused = get_focused_view(workspace);
	// if the workspace we are changing focus to has a fullscreen view return
	if (swayc_is_fullscreen(focused) && c != focused) {
		return false;
	}

	// Check if we changing a parent container that will see chnage
	bool effective = true;
	while (find != &root_container) {
		if (find->parent->focused != find) {
			effective = false;
		}
		find = find->parent;
	}
	if (effective) {
		// Go to set_focused_container
		return set_focused_container(c);
	}

	sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld",
		a, a->handle, c, c->handle);

	c->is_focused = true;
	swayc_t *p = c;
	while (p != a) {
		update_focus(p);
		p = p->parent;
		p->is_focused = false;
	}
	return true;
}
Ejemplo n.º 8
0
static void set_lock_surface(struct wl_client *client, struct wl_resource *resource,
                             struct wl_resource *_output, struct wl_resource *surface) {
    swayc_t *output = swayc_by_handle(wlc_handle_from_wl_output_resource(_output));
    swayc_t *view = swayc_by_handle(wlc_handle_from_wl_surface_resource(surface));
    sway_log(L_DEBUG, "Setting lock surface to %p", view);
    if (view && output) {
        swayc_t *workspace = output->focused;
        if (!swayc_is_child_of(view, workspace)) {
            move_container_to(view, workspace);
        }
        wlc_view_set_state(view->handle, WLC_BIT_FULLSCREEN, true);
        workspace->fullscreen = view;
        desktop_shell.is_locked = true;
        set_focused_container(view);
        arrange_windows(view, -1, -1);
        list_add(desktop_shell.lock_surfaces, surface);
        wl_resource_set_destructor(surface, lock_surface_destructor);
    } else {
        sway_log(L_ERROR, "Attempted to set lock surface to non-view");
    }
}
Ejemplo n.º 9
0
void pointer_position_set(struct wlc_point *new_origin, bool force_focus) {
	struct wlc_point origin;
	wlc_pointer_get_position(&origin);
	pointer_state.delta.x = new_origin->x - origin.x;
	pointer_state.delta.y = new_origin->y - origin.y;

	wlc_pointer_set_position(new_origin);

	// Update view under pointer
	swayc_t *prev_view = pointer_state.view;
	pointer_state.view = container_under_pointer();

	// If pointer is in a mode, update it
	if (pointer_state.mode) {
		pointer_mode_update();
	// Otherwise change focus if config is set
	} else if (force_focus || (prev_view != pointer_state.view && config->focus_follows_mouse)) {
		if (pointer_state.view && pointer_state.view->type == C_VIEW) {
			set_focused_container(pointer_state.view);
		}
	}
}
Ejemplo n.º 10
0
void workspace_switch(swayc_t *workspace) {
	if (!workspace) {
		return;
	}
	swayc_t *active_ws = swayc_active_workspace();
	if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) {
		swayc_t *new_ws = workspace_by_name(prev_workspace_name);
		workspace = new_ws ? new_ws : workspace_create(prev_workspace_name);
	}

	if (!prev_workspace_name
			|| (strcmp(prev_workspace_name, active_ws->name)
				&& active_ws != workspace)) {
		free(prev_workspace_name);
		prev_workspace_name = malloc(strlen(active_ws->name)+1);
		strcpy(prev_workspace_name, active_ws->name);
	}

	sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name);
	set_focused_container(get_focused_view(workspace));
	arrange_windows(workspace, -1, -1);
}
Ejemplo n.º 11
0
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
	// Update pointer origin
	pointer_state.delta.x = origin->x - pointer_state.origin.x;
	pointer_state.delta.y = origin->y - pointer_state.origin.y;
	pointer_state.origin.x = origin->x;
	pointer_state.origin.y = origin->y;

	// Update view under pointer
	swayc_t *prev_view = pointer_state.view;
	pointer_state.view = container_under_pointer();

	// If pointer is in a mode, update it
	if (pointer_state.mode) {
		pointer_mode_update();
	}
	// Otherwise change focus if config is set an
	else if (prev_view != pointer_state.view && config->focus_follows_mouse) {
		if (pointer_state.view && pointer_state.view->type == C_VIEW) {
			set_focused_container(pointer_state.view);
		}
	}
	return EVENT_PASSTHROUGH;
}
Ejemplo n.º 12
0
static bool handle_view_created(wlc_handle handle) {
	swayc_t *focused = get_focused_container(&root_container);
	swayc_t *newview = NULL;
	switch (wlc_view_get_type(handle)) {
	// regular view created regularly
	case 0:
		newview = new_view(focused, handle);
		wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
		break;
	// takes keyboard focus
	case WLC_BIT_OVERRIDE_REDIRECT:
		sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle);
		locked_view_focus = true;
		wlc_view_focus(handle);
		wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
		wlc_view_bring_to_front(handle);
		break;
	// Takes container focus
	case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
		sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle);
		wlc_view_bring_to_front(handle);
		locked_container_focus = true;
		break;
	// set modals as floating containers
	case WLC_BIT_MODAL:
		wlc_view_bring_to_front(handle);
		newview = new_floating_view(handle);
	case WLC_BIT_POPUP:
		break;
	}
	if (newview) {
		set_focused_container(newview);
		arrange_windows(newview->parent, -1, -1);
	}
	return true;
}
Ejemplo n.º 13
0
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
	static struct wlc_origin prev_pos;
	static wlc_handle prev_handle = 0;
	mouse_origin = *origin;
	bool changed_floating = false;
	bool changed_tiling = false;
	int min_sane_w = 100;
	int min_sane_h = 60;
	if (!active_workspace) {
		return false;
	}
	// Do checks to determine if proper keys are being held
	swayc_t *view = container_under_pointer();
	uint32_t edge = 0;
	if (pointer_state.floating.drag && view) {
		if (view->is_floating) {
			int dx = mouse_origin.x - prev_pos.x;
			int dy = mouse_origin.y - prev_pos.y;
			view->x += dx;
			view->y += dy;
			changed_floating = true;
		}
	} else if (pointer_state.floating.resize && view) {
		if (view->is_floating) {
			int dx = mouse_origin.x - prev_pos.x;
			int dy = mouse_origin.y - prev_pos.y;

			// Move and resize the view based on the dx/dy and mouse position
			int midway_x = view->x + view->width/2;
			int midway_y = view->y + view->height/2;
			if (dx < 0) {
				if (!pointer_state.lock.right) {
					if (view->width > min_sane_w) {
						changed_floating = true;
						view->width += dx;
						edge += WLC_RESIZE_EDGE_RIGHT;
					}
				} else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
					changed_floating = true;
					view->x += dx;
					view->width -= dx;
					edge += WLC_RESIZE_EDGE_LEFT;
				}
			} else if (dx > 0) {
				if (mouse_origin.x > midway_x && !pointer_state.lock.right) {
					changed_floating = true;
					view->width += dx;
					edge += WLC_RESIZE_EDGE_RIGHT;
				} else if (!pointer_state.lock.left) {
					if (view->width > min_sane_w) {
						changed_floating = true;
						view->x += dx;
						view->width -= dx;
						edge += WLC_RESIZE_EDGE_LEFT;
					}
				}
			}

			if (dy < 0) {
				if (!pointer_state.lock.bottom) {
					if (view->height > min_sane_h) {
						changed_floating = true;
						view->height += dy;
						edge += WLC_RESIZE_EDGE_BOTTOM;
					}
				} else if (mouse_origin.y < midway_y && !pointer_state.lock.top) {
					changed_floating = true;
					view->y += dy;
					view->height -= dy;
					edge += WLC_RESIZE_EDGE_TOP;
				}
			} else if (dy > 0) {
				if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
					changed_floating = true;
					view->height += dy;
					edge += WLC_RESIZE_EDGE_BOTTOM;
				} else if (!pointer_state.lock.top) {
					if (view->height > min_sane_h) {
						changed_floating = true;
						view->y += dy;
						view->height -= dy;
						edge += WLC_RESIZE_EDGE_TOP;
					}
				}
			}
		}
	} else if (pointer_state.tiling.resize && view) {
		bool valid = true;
		double dx = mouse_origin.x - prev_pos.x;
		double dy = mouse_origin.y - prev_pos.y;

		if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) {
			changed_tiling = true;
			valid = false;
		} else if (dx > 0 && pointer_state.lock.temp_left) {
			pointer_state.lock.temp_left = false;
		}

		if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) {
			changed_tiling = true;
			valid = false;
		} else if (dx < 0 && pointer_state.lock.temp_right) {
			pointer_state.lock.temp_right = false;
		}

		if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) {
			changed_tiling = true;
			valid = false;
		} else if (dy > 0 && pointer_state.lock.temp_up) {
			pointer_state.lock.temp_up = false;
		}

		if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) {
			changed_tiling = true;
			valid = false;
		} else if (dy < 0 && pointer_state.lock.temp_down) {
			pointer_state.lock.temp_down = false;
		}

		if (!view->is_floating && valid) {
			// Handle layout resizes -- Find the biggest parent container then apply resizes to that
			// and its bordering siblings
			swayc_t *parent = view;
			if (!pointer_state.lock.bottom) {
				while (parent->type != C_WORKSPACE) {
					// TODO: Absolute value is a bad hack here to compensate for rounding. Find a better
					// way of doing this.
					if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) {
						parent = parent->parent;
					} else {
						break;
					}
				}
				if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
					swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN);
					if (sibling) {
						if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) {
							recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM);
							recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP);
							changed_tiling = true;
						} else {
							pointer_state.tiling.lock_pos.y = mouse_origin.y;
							if (parent->height < min_sane_h) {
								pointer_state.lock.temp_up = true;
							} else if (sibling->height < min_sane_h) {
								pointer_state.lock.temp_down = true;
							}
						}
					}
				}
			} else if (!pointer_state.lock.top) {
				while (parent->type != C_WORKSPACE) {
					if (fabs(parent->parent->y - view->y) <= 1) {
						parent = parent->parent;
					} else {
						break;
					}
				}
				if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
					swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP);
					if (sibling) {
						if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) {
							recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP);
							recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM);
							changed_tiling = true;
						} else {
							pointer_state.tiling.lock_pos.y = mouse_origin.y;
							if (parent->height < min_sane_h) {
								pointer_state.lock.temp_down = true;
							} else if (sibling->height < min_sane_h) {
								pointer_state.lock.temp_up = true;
							}
						}
					}
				}
			}

			parent = view;
			if (!pointer_state.lock.right) {
				while (parent->type != C_WORKSPACE) {
					if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) {
						parent = parent->parent;
					} else {
						sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width);
						break;
					}
				}
				if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
					swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT);
					if (sibling) {
						if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) {
							recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT);
							recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT);
							changed_tiling = true;
						} else {
							pointer_state.tiling.lock_pos.x = mouse_origin.x;
							if (parent->width < min_sane_w) {
								pointer_state.lock.temp_left = true;
							} else if (sibling->width < min_sane_w) {
								pointer_state.lock.temp_right = true;
							}
						}
					}
				}
			} else if (!pointer_state.lock.left) {
				while (parent->type != C_WORKSPACE) {
					if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) {
						parent = parent->parent;
					} else {
						break;
					}
				}
				if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
					swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT);
					if (sibling) {
						if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) {
							recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT);
							recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT);
							changed_tiling = true;
						} else {
							pointer_state.tiling.lock_pos.x = mouse_origin.x;
							if (parent->width < min_sane_w) {
								pointer_state.lock.temp_right = true;
							} else if (sibling->width < min_sane_w) {
								pointer_state.lock.temp_left = true;
							}
						}
					}
				}
			}
			arrange_windows(active_workspace, -1, -1);
		}
	}
	if (config->focus_follows_mouse && prev_handle != handle) {
		// Dont change focus if fullscreen
		swayc_t *focused = get_focused_view(view);
		if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)
				&& !(pointer_state.l_held || pointer_state.r_held)) {
			set_focused_container(container_under_pointer());
		}
	}
	prev_handle = handle;
	prev_pos = mouse_origin;
	if (changed_floating) {
		struct wlc_geometry geometry = {
			.origin = {
				.x = view->x,
				.y = view->y
			},
			.size = {
				.w = view->width,
				.h = view->height
			}
		};
		wlc_view_set_geometry(view->handle, edge, &geometry);
		return true;
	}
Ejemplo n.º 14
0
struct cmd_results *cmd_floating(int argc, char **argv) {
	struct cmd_results *error = NULL;
	if (config->reading) return cmd_results_new(CMD_FAILURE, "floating", "Can't be used in config file.");
	if ((error = checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1))) {
		return error;
	}
	swayc_t *view = current_container;
	bool wants_floating;
	if (strcasecmp(argv[0], "enable") == 0) {
		wants_floating = true;
	} else if (strcasecmp(argv[0], "disable") == 0) {
		wants_floating = false;
	} else if (strcasecmp(argv[0], "toggle") == 0) {
		wants_floating = !view->is_floating;
	} else {
		return cmd_results_new(CMD_FAILURE, "floating",
			"Expected 'floating <enable|disable|toggle>");
	}

	// Prevent running floating commands on things like workspaces
	if (view->type != C_VIEW) {
		return cmd_results_new(CMD_SUCCESS, NULL, NULL);
	}

	// Change from nonfloating to floating
	if (!view->is_floating && wants_floating) {
		// Remove view from its current location
		destroy_container(remove_child(view));

		// and move it into workspace floating
		add_floating(swayc_active_workspace(), view);
		view->x = (swayc_active_workspace()->width - view->width)/2;
		view->y = (swayc_active_workspace()->height - view->height)/2;
		if (view->desired_width != -1) {
			view->width = view->desired_width;
		}
		if (view->desired_height != -1) {
			view->height = view->desired_height;
		}
		arrange_windows(swayc_active_workspace(), -1, -1);

	} else if (view->is_floating && !wants_floating) {
		// Delete the view from the floating list and unset its is_floating flag
		remove_child(view);
		view->is_floating = false;
		// Get the properly focused container, and add in the view there
		swayc_t *focused = container_under_pointer();
		// If focused is null, it's because the currently focused container is a workspace
		if (focused == NULL || focused->is_floating) {
			focused = swayc_active_workspace();
		}
		set_focused_container(focused);

		sway_log(L_DEBUG, "Non-floating focused container is %p", focused);

		// Case of focused workspace, just create as child of it
		if (focused->type == C_WORKSPACE) {
			add_child(focused, view);
		}
		// Regular case, create as sibling of current container
		else {
			add_sibling(focused, view);
		}
		// Refocus on the view once its been put back into the layout
		view->width = view->height = 0;
		arrange_windows(swayc_active_workspace(), -1, -1);
		remove_view_from_scratchpad(view);
		ipc_event_window(view, "floating");
	}
	set_focused_container(view);
	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
Ejemplo n.º 15
0
static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
		uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) {

	// Update view pointer is on
	pointer_state.view = container_under_pointer();

	// Update pointer origin
	pointer_state.origin.x = origin->x;
	pointer_state.origin.y = origin->y;

	// Update pointer_state
	switch (button) {
	case M_LEFT_CLICK:
		if (state == WLC_BUTTON_STATE_PRESSED) {
			pointer_state.left.held = true;
			pointer_state.left.x = origin->x;
			pointer_state.left.y = origin->y;
			pointer_state.left.view = pointer_state.view;
		} else {
			pointer_state.left.held = false;
		}
		break;

	case M_RIGHT_CLICK:
		if (state == WLC_BUTTON_STATE_PRESSED) {
			pointer_state.right.held = true;
			pointer_state.right.x = origin->x;
			pointer_state.right.y = origin->y;
			pointer_state.right.view = pointer_state.view;
		} else {
			pointer_state.right.held = false;
		}
		break;

	case M_SCROLL_CLICK:
		if (state == WLC_BUTTON_STATE_PRESSED) {
			pointer_state.scroll.held = true;
			pointer_state.scroll.x = origin->x;
			pointer_state.scroll.y = origin->y;
			pointer_state.scroll.view = pointer_state.view;
		} else {
			pointer_state.scroll.held = false;
		}
		break;

		//TODO scrolling behavior
	case M_SCROLL_UP:
	case M_SCROLL_DOWN:
		break;
	}

	// get focused window and check if to change focus on mouse click
	swayc_t *focused = get_focused_container(&root_container);

	// dont change focus or mode if fullscreen
	if (swayc_is_fullscreen(focused)) {
		return EVENT_PASSTHROUGH;
	}

	// set pointer mode only if floating mod has been set
	if (config->floating_mod) {
		pointer_mode_set(button, !(modifiers->mods ^ config->floating_mod));
	}

	// Check whether to change focus
	swayc_t *pointer = pointer_state.view;
	if (pointer) {
		if (focused != pointer) {
			set_focused_container(pointer_state.view);
		}
		// Send to front if floating
		if (pointer->is_floating) {
			int i;
			for (i = 0; i < pointer->parent->floating->length; i++) {
				if (pointer->parent->floating->items[i] == pointer) {
					list_del(pointer->parent->floating, i);
					list_add(pointer->parent->floating, pointer);
					break;
				}
			}
			wlc_view_bring_to_front(pointer->handle);
		}
	}

	// Return if mode has been set
	if (pointer_state.mode) {
		return EVENT_HANDLED;
	}

	// Always send mouse release
	if (state == WLC_BUTTON_STATE_RELEASED) {
		return EVENT_PASSTHROUGH;
	}

	// Finally send click
	return EVENT_PASSTHROUGH;
}
Ejemplo n.º 16
0
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
	static struct wlc_origin prev_pos;
	static wlc_handle prev_handle = 0;
	mouse_origin = *origin;
	bool changed_floating = false;
	int i = 0;
	// Do checks to determine if proper keys are being held
	swayc_t *view = active_workspace->focused;
	if (m1_held && view) {
		if (view->is_floating) {
			while (keys_pressed[i++]) {
				if (keys_pressed[i] == config->floating_mod) {
					int dx = mouse_origin.x - prev_pos.x;
					int dy = mouse_origin.y - prev_pos.y;
					sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y);
					sway_log(L_DEBUG, "Moving: dx: %d, dy: %d", dx, dy);

					view->x += dx;
					view->y += dy;
					changed_floating = true;
					break;
				}
			}
		}
	} else if (m2_held && view) {
		if (view->is_floating) {
			while (keys_pressed[i++]) {
				if (keys_pressed[i] == config->floating_mod) {
					int dx = mouse_origin.x - prev_pos.x;
					int dy = mouse_origin.y - prev_pos.y;
					sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y);
					sway_log(L_INFO, "Moving: dx: %d, dy: %d", dx, dy);

					// Move and resize the view based on the dx/dy and mouse position
					int midway_x = view->x + view->width/2;
					int midway_y = view->y + view->height/2;

					if (dx < 0) {
						changed_floating = true;
						if (mouse_origin.x > midway_x) {
							sway_log(L_INFO, "Downsizing view to the left");
							view->width += dx;
						} else {
							sway_log(L_INFO, "Upsizing view to the left");
							view->x += dx;
							view->width -= dx;
						}
					} else if (dx > 0){
						changed_floating = true;
						if (mouse_origin.x > midway_x) {
							sway_log(L_INFO, "Upsizing to the right");
							view->width += dx;
						} else {
							sway_log(L_INFO, "Downsizing to the right");
							view->x += dx;
							view->width -= dx;
						}
					}

					if (dy < 0) {
						changed_floating = true;
						if (mouse_origin.y > midway_y) {
							sway_log(L_INFO, "Downsizing view to the top");
							view->height += dy;
						} else {
							sway_log(L_INFO, "Upsizing the view to the top");
							view->y += dy;
							view->height -= dy;
						}
					} else if (dy > 0) {
						changed_floating = true;
						if (mouse_origin.y > midway_y) {
							sway_log(L_INFO, "Upsizing to the bottom");
							view->height += dy;
						} else {
							sway_log(L_INFO, "Downsizing to the bottom");
							view->y += dy;
							view->height -= dy;
						}
					}
					break;
				}
			}
		}
	}
	if (config->focus_follows_mouse && prev_handle != handle) {
		set_focused_container(container_under_pointer());
	}
	prev_handle = handle;
	prev_pos = mouse_origin;
	if (changed_floating) {
		arrange_windows(view, -1, -1);
		return true;
	}
	return false;
}
Ejemplo n.º 17
0
static bool handle_view_created(wlc_handle handle) {
	// if view is child of another view, the use that as focused container
	wlc_handle parent = wlc_view_get_parent(handle);
	swayc_t *focused = NULL;
	swayc_t *newview = NULL;

	// Get parent container, to add view in
	if (parent) {
		focused = get_swayc_for_handle(parent, &root_container);
	}
	if (!focused || focused->type == C_OUTPUT) {
		focused = get_focused_container(&root_container);
	}
	sway_log(L_DEBUG, "handle:%ld type:%x state:%x parent:%ld "
			"mask:%d (x:%d y:%d w:%d h:%d) title:%s "
			"class:%s appid:%s",
		handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent,
		wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x,
		wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w,
		wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle),
		wlc_view_get_class(handle), wlc_view_get_app_id(handle));

	// TODO properly figure out how each window should be handled.
	switch (wlc_view_get_type(handle)) {
	// regular view created regularly
	case 0:
		newview = new_view(focused, handle);
		wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
		break;

	// Dmenu keeps viewfocus, but others with this flag dont, for now simulate
	// dmenu
	case WLC_BIT_OVERRIDE_REDIRECT:
// 		locked_view_focus = true;
		wlc_view_focus(handle);
		wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
		wlc_view_bring_to_front(handle);
		break;

	// Firefox popups have this flag set.
	case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
		wlc_view_bring_to_front(handle);
		locked_container_focus = true;
		break;

	// Modals, get focus, popups do not
	case WLC_BIT_MODAL:
		wlc_view_focus(handle);
		wlc_view_bring_to_front(handle);
		newview = new_floating_view(handle);
	case WLC_BIT_POPUP:
		wlc_view_bring_to_front(handle);
		break;
	}

	if (newview) {
		set_focused_container(newview);
		swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT);
		arrange_windows(output, -1, -1);
	}
	return true;
}
Ejemplo n.º 18
0
void pointer_mode_update(void) {
	if (initial.ptr->type != C_VIEW) {
		pointer_state.mode = 0;
		return;
	}
	struct wlc_point origin;
	wlc_pointer_get_position(&origin);
	int dx = origin.x;
	int dy = origin.y;

	switch (pointer_state.mode) {
	case M_FLOATING | M_DRAGGING:
		// Update position
		switch (config->dragging_key) {
		case M_LEFT_CLICK:
			dx -= pointer_state.left.x;
			dy -= pointer_state.left.y;
			break;
		case M_RIGHT_CLICK:
			dx -= pointer_state.right.x;
			dy -= pointer_state.right.y;
			break;
		}

		if (initial.x + dx != initial.ptr->x) {
			initial.ptr->x = initial.x + dx;
		}
		if (initial.y + dy != initial.ptr->y) {
			initial.ptr->y = initial.y + dy;
		}
		update_geometry(initial.ptr);
		break;

	case M_FLOATING | M_RESIZING:
		switch (config->resizing_key) {
		case M_LEFT_CLICK:
			dx -= pointer_state.left.x;
			dy -= pointer_state.left.y;
			initial.ptr = pointer_state.left.view;
			break;
		case M_RIGHT_CLICK:
			dx -= pointer_state.right.x;
			dy -= pointer_state.right.y;
			initial.ptr = pointer_state.right.view;
			break;
		}

		if (lock.left) {
			if (initial.w + dx > min_sane_w) {
				initial.ptr->width = initial.w + dx;
			}
		} else { // lock.right
			if (initial.w - dx > min_sane_w) {
				initial.ptr->width = initial.w - dx;
				initial.ptr->x = initial.x + dx;
			}
		}
		if (lock.top) {
			if (initial.h + dy > min_sane_h) {
				initial.ptr->height = initial.h + dy;
			}
		} else { // lock.bottom
			if (initial.h - dy > min_sane_h) {
				initial.ptr->height = initial.h - dy;
				initial.ptr->y = initial.y + dy;
			}
		}
		update_geometry(initial.ptr);
		break;

	case M_TILING | M_DRAGGING:
		// swap current view under pointer with dragged view
		if (pointer_state.view && pointer_state.view->type == C_VIEW
				&& pointer_state.view != initial.ptr
				&& !pointer_state.view->is_floating) {
			// Swap them around
			swap_container(pointer_state.view, initial.ptr);
			swap_geometry(pointer_state.view, initial.ptr);
			update_geometry(pointer_state.view);
			update_geometry(initial.ptr);
			// Set focus back to initial view
			set_focused_container(initial.ptr);
		}
		break;

	case M_TILING | M_RESIZING:
		switch (config->resizing_key) {
		case M_LEFT_CLICK:
			dx -= pointer_state.left.x;
			dy -= pointer_state.left.y;
			break;
		case M_RIGHT_CLICK:
			dx -= pointer_state.right.x;
			dy -= pointer_state.right.y;
			break;
		}

		// resize if we can
		if (initial.horiz.ptr) {
			if (lock.left) {
				// Check whether its fine to resize
				if (initial.w + dx > min_sane_w && initial.horiz.w - dx > min_sane_w) {
					initial.horiz.ptr->width = initial.horiz.w - dx;
					initial.horiz.parent.ptr->width = initial.horiz.parent.w + dx;
				}
			} else { // lock.right
				if (initial.w - dx > min_sane_w && initial.horiz.w + dx > min_sane_w) {
					initial.horiz.ptr->width = initial.horiz.w + dx;
					initial.horiz.parent.ptr->width = initial.horiz.parent.w - dx;
				}
			}
			arrange_windows(initial.horiz.ptr->parent, -1, -1);
		}
		if (initial.vert.ptr) {
			if (lock.top) {
				if (initial.h + dy > min_sane_h && initial.vert.h - dy > min_sane_h) {
					initial.vert.ptr->height = initial.vert.h - dy;
					initial.vert.parent.ptr->height = initial.vert.parent.h + dy;
				}
			} else { // lock.bottom
				if (initial.h - dy > min_sane_h && initial.vert.h + dy > min_sane_h) {
					initial.vert.ptr->height = initial.vert.h + dy;
					initial.vert.parent.ptr->height = initial.vert.parent.h - dy;
				}
			}
			arrange_windows(initial.vert.ptr->parent, -1, -1);
		}
	default:
		return;
	}
}
Ejemplo n.º 19
0
bool move_focus(enum movement_direction direction) {
	if (locked_container_focus) {
		return false;
	}
	swayc_t *current = get_focused_container(&root_container);
	swayc_t *parent = current->parent;

	if (direction == MOVE_PARENT) {
		if (parent->type == C_OUTPUT) {
			sway_log(L_DEBUG, "Focus cannot move to parent");
			return false;
		} else {
			sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld",
				current, current->handle, parent, parent->handle);
			set_focused_container(parent);
			return true;
		}
	}

	while (true) {
		sway_log(L_DEBUG, "Moving focus away from %p", current);

		// Test if we can even make a difference here
		bool can_move = false;
		int diff = 0;
		if (direction == MOVE_LEFT || direction == MOVE_RIGHT) {
			if (parent->layout == L_HORIZ || parent->type == C_ROOT) {
				can_move = true;
				diff = direction == MOVE_LEFT ? -1 : 1;
			}
		} else {
			if (parent->layout == L_VERT) {
				can_move = true;
				diff = direction == MOVE_UP ? -1 : 1;
			}
		}
		sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no");
		if (can_move) {
			int i;
			for (i = 0; i < parent->children->length; ++i) {
				swayc_t *child = parent->children->items[i];
				if (child == current) {
					break;
				}
			}
			int desired = i + diff;
			sway_log(L_DEBUG, "Moving from %d to %d", i, desired);
			if (desired < 0 || desired >= parent->children->length) {
				can_move = false;
			} else {
				swayc_t *newview = parent->children->items[desired];
				set_focused_container(get_focused_view(newview));
				return true;
			}
		}
		if (!can_move) {
			sway_log(L_DEBUG, "Can't move at current level, moving up tree");
			current = parent;
			parent = parent->parent;
			if (!parent) {
				// Nothing we can do
				return false;
			}
		}
	}
}