Exemple #1
0
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
	swayc_t *c = get_swayc_for_handle(view, &root_container);
	switch (state) {
	case WLC_BIT_FULLSCREEN:
		// i3 just lets it become fullscreen
		wlc_view_set_state(view, state, toggle);
		if (c) {
			sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle);
			arrange_windows(c->parent, -1, -1);
			// Set it as focused window for that workspace if its going fullscreen
			if (toggle) {
				swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE);
				// Set ws focus to c
				set_focused_container_for(ws, c);
			}
		}
		break;
	case WLC_BIT_MAXIMIZED:
	case WLC_BIT_RESIZING:
	case WLC_BIT_MOVING:
		break;
	case WLC_BIT_ACTIVATED:
		sway_log(L_DEBUG, "View %p requested to be activated", c);
		break;
	}
	return;
}
struct cmd_results *cmd_floating_maximum_size(int argc, char **argv) {
	struct cmd_results *error = NULL;
	int32_t width;
	int32_t height;
	char *ptr;

	if ((error = checkarg(argc, "floating_maximum_size", EXPECTED_EQUAL_TO, 3))) {
		return error;
	}
	width = strtol(argv[0], &ptr, 10);
	height = strtol(argv[2], &ptr, 10);

	if (width < -1) {
		sway_log(L_DEBUG, "floating_maximum_size invalid width value: '%s'", argv[0]);

	} else {
		config->floating_maximum_width = width;

	}

	if (height < -1) {
		sway_log(L_DEBUG, "floating_maximum_size invalid height value: '%s'", argv[2]);
	}
	else {
		config->floating_maximum_height = height;

	}

	sway_log(L_DEBUG, "New floating_maximum_size: '%d' x '%d'", config->floating_maximum_width,
		config->floating_maximum_height);

	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
Exemple #3
0
void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
	struct wlr_xdg_surface_v6 *xdg_surface = data;

	if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
		sway_log(SWAY_DEBUG, "New xdg_shell_v6 popup");
		return;
	}

	sway_log(SWAY_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'",
		xdg_surface->toplevel->title, xdg_surface->toplevel->app_id);
	wlr_xdg_surface_v6_ping(xdg_surface);

	struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
		calloc(1, sizeof(struct sway_xdg_shell_v6_view));
	if (!sway_assert(xdg_shell_v6_view, "Failed to allocate view")) {
		return;
	}

	view_init(&xdg_shell_v6_view->view, SWAY_VIEW_XDG_SHELL_V6, &view_impl);
	xdg_shell_v6_view->view.wlr_xdg_surface_v6 = xdg_surface;

	xdg_shell_v6_view->map.notify = handle_map;
	wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map);

	xdg_shell_v6_view->unmap.notify = handle_unmap;
	wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_v6_view->unmap);

	xdg_shell_v6_view->destroy.notify = handle_destroy;
	wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_v6_view->destroy);

	xdg_surface->data = xdg_shell_v6_view;
}
Exemple #4
0
bool load_config(const char *file) {
	input_init();

	char *path;
	if (file != NULL) {
		path = strdup(file);
	} else {
		path = get_config_path();
	}

	sway_log(L_INFO, "Loading config from %s", path);

	if (path == NULL) {
		sway_log(L_ERROR, "Unable to find a config file!");
		return false;
	}

	FILE *f = fopen(path, "r");
	if (!f) {
		fprintf(stderr, "Unable to open %s for reading", path);
		free(path);
		return false;
	}
	free(path);

	bool config_load_success;
	if (config) {
		config_load_success = read_config(f, true);
	} else {
		config_load_success = read_config(f, false);
	}
	fclose(f);

	return config_load_success;
}
Exemple #5
0
void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
		const char *fmt, ...) {
	if (!swaynag_command) {
		return;
	}

	if (!swaynag->detailed) {
		sway_log(SWAY_ERROR, "Attempting to write to non-detailed swaynag inst");
		return;
	}

	if (swaynag->pid <= 0 && !swaynag_spawn(swaynag_command, swaynag)) {
		return;
	}

	va_list args;
	va_start(args, fmt);
	size_t length = vsnprintf(NULL, 0, fmt, args) + 1;
	va_end(args);

	char *temp = malloc(length + 1);
	if (!temp) {
		sway_log(SWAY_ERROR, "Failed to allocate buffer for swaynag log entry.");
		return;
	}

	va_start(args, fmt);
	vsnprintf(temp, length, fmt, args);
	va_end(args);

	write(swaynag->fd[1], temp, length);

	free(temp);
}
Exemple #6
0
char *libinput_dev_unique_id(struct libinput_device *device) {
	int vendor = libinput_device_get_id_vendor(device);
	int product = libinput_device_get_id_product(device);
	char *name = strdup(libinput_device_get_name(device));

	char *p = name;
	for (; *p; ++p) {
		if (*p == ' ') {
			*p = '_';
		}
	}

	sway_log(L_DEBUG, "rewritten name %s", name);

	int len = strlen(name) + sizeof(char) * 6;
	char *identifier = malloc(len);
	if (!identifier) {
		sway_log(L_ERROR, "Unable to allocate unique input device name");
		return NULL;
	}

	const char *fmt = "%d:%d:%s";
	snprintf(identifier, len, fmt, vendor, product, name);
	free(name);
	return identifier;
}
Exemple #7
0
struct input_config *new_input_config(const char* identifier) {
	struct input_config *input = calloc(1, sizeof(struct input_config));
	if (!input) {
		sway_log(L_DEBUG, "Unable to allocate input config");
		return NULL;
	}
	sway_log(L_DEBUG, "new_input_config(%s)", identifier);
	if (!(input->identifier = strdup(identifier))) {
		free(input);
		sway_log(L_DEBUG, "Unable to allocate input config");
		return NULL;
	}

	input->tap = INT_MIN;
	input->drag_lock = INT_MIN;
	input->dwt = INT_MIN;
	input->send_events = INT_MIN;
	input->click_method = INT_MIN;
	input->middle_emulation = INT_MIN;
	input->natural_scroll = INT_MIN;
	input->accel_profile = INT_MIN;
	input->pointer_accel = FLT_MIN;
	input->scroll_method = INT_MIN;
	input->left_handed = INT_MIN;

	return input;
}
Exemple #8
0
static bool load_config(const char *path, struct sway_config *config) {
	sway_log(L_INFO, "Loading config from %s", path);
	current_config_path = path;

	struct stat sb;
	if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
		return false;
	}

	if (path == NULL) {
		sway_log(L_ERROR, "Unable to find a config file!");
		return false;
	}

	FILE *f = fopen(path, "r");
	if (!f) {
		sway_log(L_ERROR, "Unable to open %s for reading", path);
		return false;
	}

	bool config_load_success = read_config(f, config);
	fclose(f);

	if (!config_load_success) {
		sway_log(L_ERROR, "Error(s) loading config!");
	}

	current_config_path = NULL;
	return true;
}
Exemple #9
0
bool read_config(FILE *file, bool is_active) {
	struct sway_config *temp_config = malloc(sizeof(struct sway_config));
	config_defaults(temp_config);
	if (is_active) {
		sway_log(L_DEBUG, "Performing configuration file reload");
		temp_config->reloading = true;
		temp_config->active = true;
	}

	bool success = true;

	int temp_depth = 0; // Temporary: skip all config sections with depth

	while (!feof(file)) {
		int _;
		char *line = read_line(file);
		line = strip_whitespace(line, &_);
		line = strip_comments(line);
		if (!line[0]) {
			goto _continue;
		}
		if (temp_depth && line[0] == '}') {
			temp_depth--;
			goto _continue;
		}

		// Any command which would require wlc to be initialized
		// should be queued for later execution
		list_t *args = split_string(line, " ");
		if (!is_active && (
			strcmp("exec", args->items[0]) == 0 ||
			strcmp("exec_always", args->items[0]) == 0 )) {
			sway_log(L_DEBUG, "Deferring command %s", line);

			char *cmd = malloc(strlen(line) + 1);
			strcpy(cmd, line);
			list_add(temp_config->cmd_queue, cmd);
		} else if (!temp_depth && !handle_command(temp_config, line)) {
			sway_log(L_DEBUG, "Config load failed for line %s", line);
			success = false;
			temp_config->failed = true;
		}
		list_free(args);

_continue:
		if (line && line[strlen(line) - 1] == '{') {
			temp_depth++;
		}
		free(line);
	}

	if (is_active) {
		temp_config->reloading = false;
		container_map(&root_container, reset_gaps, NULL);
		arrange_windows(&root_container, -1, -1);
	}
	config = temp_config;

	return success;
}
Exemple #10
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) {
	swayc_t *focused = get_focused_container(&root_container);
	if (state == WLC_BUTTON_STATE_PRESSED) {
		sway_log(L_DEBUG, "Mouse button %u pressed", button);
		if (button == 272) {
			m1_held = true;
		}
		if (button == 273) {
			m2_held = true;
		}
		swayc_t *pointer = container_under_pointer();
		set_focused_container(pointer);
		return (pointer && pointer != focused);
	} else {
		sway_log(L_DEBUG, "Mouse button %u released", button);
		if (button == 272) {
			m1_held = false;
		}
		if (button == 273) {
			m2_held = false;
		}
	}
	return false;
}
Exemple #11
0
int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
	struct ipc_client *client = data;

	if (mask & WLC_EVENT_ERROR) {
		sway_log(L_INFO, "IPC Client socket error, removing client");
		client->fd = -1;
		ipc_client_disconnect(client);
		return 0;
	}

	if (mask & WLC_EVENT_HANGUP) {
		client->fd = -1;
		ipc_client_disconnect(client);
		return 0;
	}

	int read_available;
	if (ioctl(client_fd, FIONREAD, &read_available) == -1) {
		sway_log_errno(L_INFO, "Unable to read IPC socket buffer size");
		ipc_client_disconnect(client);
		return 0;
	}

	// Wait for the rest of the command payload in case the header has already been read
	if (client->payload_length > 0) {
		if ((uint32_t)read_available >= client->payload_length) {
			ipc_client_handle_command(client);
		}
		return 0;
	}

	if (read_available < ipc_header_size) {
		return 0;
	}

	uint8_t buf[ipc_header_size];
	uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic));
	ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
	if (received == -1) {
		sway_log_errno(L_INFO, "Unable to receive header from IPC client");
		ipc_client_disconnect(client);
		return 0;
	}

	if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) {
		sway_log(L_DEBUG, "IPC header check failed");
		ipc_client_disconnect(client);
		return 0;
	}

	client->payload_length = buf32[0];
	client->current_command = (enum ipc_command_type)buf32[1];

	if (read_available - received >= (long)client->payload_length) {
		ipc_client_handle_command(client);
	}

	return 0;
}
Exemple #12
0
char *workspace_next_name(void) {
	sway_log(L_DEBUG, "Workspace: Generating new name");
	int i;
	int l = 1;
	// Scan all workspace bindings to find the next available workspace name,
	// if none are found/available then default to a number
	struct sway_mode *mode = config->current_mode;

	for (i = 0; i < mode->bindings->length; ++i) {
		struct sway_binding *binding = mode->bindings->items[i];
		const char* command = binding->command;
		list_t *args = split_string(command, " ");

		if (strcmp("workspace", args->items[0]) == 0 && args->length > 1) {
			sway_log(L_DEBUG, "Got valid workspace command for target: '%s'", (char *)args->items[1]);
			char* target = malloc(strlen(args->items[1]) + 1);
			strcpy(target, args->items[1]);
			while (*target == ' ' || *target == '\t')
				target++;

			// Make sure that the command references an actual workspace
			// not a command about workspaces
			if (strcmp(target, "next") == 0 ||
				strcmp(target, "prev") == 0 ||
				strcmp(target, "next_on_output") == 0 ||
				strcmp(target, "prev_on_output") == 0 ||
				strcmp(target, "number") == 0 ||
				strcmp(target, "back_and_forth") == 0 ||
				strcmp(target, "current") == 0)
			{
				free_flat_list(args);
				continue;
			}

			// Make sure that the workspace doesn't already exist
			if (workspace_by_name(target)) {
				free_flat_list(args);
				continue;
			}

			free_flat_list(args);

			sway_log(L_DEBUG, "Workspace: Found free name %s", target);
			return target;
		}
		free_flat_list(args);
	}
	// As a fall back, get the current number of active workspaces
	// and return that + 1 for the next workspace's name
	int ws_num = root_container.children->length;
	if (ws_num >= 10) {
		l = 2;
	} else if (ws_num >= 100) {
		l = 3;
	}
	char *name = malloc(l + 1);
	sprintf(name, "%d", ws_num++);
	return name;
}
Exemple #13
0
static void wlc_log_handler(enum wlc_log_type type, const char *str) {
	if (type == WLC_LOG_ERROR) {
		sway_log(L_ERROR, "[wlc] %s", str);
	} else if (type == WLC_LOG_WARN) {
		sway_log(L_INFO, "[wlc] %s", str);
	} else {
		sway_log(L_DEBUG, "[wlc] %s", str);
	}
}
Exemple #14
0
void bar_run(struct bar *bar) {
	int pfds = bar->outputs->length + 2;
	struct pollfd *pfd = malloc(pfds * sizeof(struct pollfd));
	bool dirty = true;

	pfd[0].fd = bar->ipc_event_socketfd;
	pfd[0].events = POLLIN;
	pfd[1].fd = bar->status_read_fd;
	pfd[1].events = POLLIN;

	int i;
	for (i = 0; i < bar->outputs->length; ++i) {
		struct output *output = bar->outputs->items[i];
		pfd[i+2].fd = wl_display_get_fd(output->registry->display);
		pfd[i+2].events = POLLIN;
	}

	while (1) {
		if (dirty) {
			int i;
			for (i = 0; i < bar->outputs->length; ++i) {
				struct output *output = bar->outputs->items[i];
				if (window_prerender(output->window) && output->window->cairo) {
					render(output, bar->config, bar->status);
					window_render(output->window);
					wl_display_flush(output->registry->display);
				}
			}
		}

		dirty = false;

		poll(pfd, pfds, -1);

		if (pfd[0].revents & POLLIN) {
			sway_log(L_DEBUG, "Got IPC event.");
			dirty = handle_ipc_event(bar);
		}

		if (bar->config->status_command && pfd[1].revents & POLLIN) {
			sway_log(L_DEBUG, "Got update from status command.");
			dirty = handle_status_line(bar);
		}

		// dispatch wl_display events
		for (i = 0; i < bar->outputs->length; ++i) {
			struct output *output = bar->outputs->items[i];
			if (pfd[i+2].revents & POLLIN) {
				if (wl_display_dispatch(output->registry->display) == -1) {
					sway_log(L_ERROR, "failed to dispatch wl: %d", errno);
				}
			} else {
				wl_display_dispatch_pending(output->registry->display);
			}
		}
	}
}
Exemple #15
0
void arrange_workspace(struct sway_workspace *workspace) {
	if (config->reloading) {
		return;
	}
	if (!workspace->output) {
		// Happens when there are no outputs connected
		return;
	}
	struct sway_output *output = workspace->output;
	struct wlr_box *area = &output->usable_area;
	sway_log(SWAY_DEBUG, "Usable area for ws: %dx%d@%d,%d",
			area->width, area->height, area->x, area->y);
	workspace_remove_gaps(workspace);

	bool first_arrange = workspace->width == 0 && workspace->height == 0;
	double prev_x = workspace->x;
	double prev_y = workspace->y;
	workspace->width = area->width;
	workspace->height = area->height;
	workspace->x = output->wlr_output->lx + area->x;
	workspace->y = output->wlr_output->ly + area->y;

	// Adjust any floating containers
	double diff_x = workspace->x - prev_x;
	double diff_y = workspace->y - prev_y;
	if (!first_arrange && (diff_x != 0 || diff_y != 0)) {
		for (int i = 0; i < workspace->floating->length; ++i) {
			struct sway_container *floater = workspace->floating->items[i];
			container_floating_translate(floater, diff_x, diff_y);
			double center_x = floater->x + floater->width / 2;
			double center_y = floater->y + floater->height / 2;
			struct wlr_box workspace_box;
			workspace_get_box(workspace, &workspace_box);
			if (!wlr_box_contains_point(&workspace_box, center_x, center_y)) {
				container_floating_move_to_center(floater);
			}
		}
	}

	workspace_add_gaps(workspace);
	node_set_dirty(&workspace->node);
	sway_log(SWAY_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name,
			workspace->x, workspace->y);
	if (workspace->fullscreen) {
		struct sway_container *fs = workspace->fullscreen;
		fs->x = output->lx;
		fs->y = output->ly;
		fs->width = output->width;
		fs->height = output->height;
		arrange_container(fs);
	} else {
		struct wlr_box box;
		workspace_get_box(workspace, &box);
		arrange_children(workspace->tiling, workspace->layout, &box);
		arrange_floating(workspace->floating);
	}
}
Exemple #16
0
int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
	struct ipc_client *client = data;
	sway_log(L_DEBUG, "Event on IPC client socket %d", client_fd);

	if (mask & WLC_EVENT_ERROR) {
		sway_log(L_INFO, "IPC Client socket error, removing client");
		ipc_client_disconnect(client);
		return 0;
	}

	if (mask & WLC_EVENT_HANGUP) {
		ipc_client_disconnect(client);
		return 0;
	}

	int read_available;
	ioctl(client_fd, FIONREAD, &read_available);

	// Wait for the rest of the command payload in case the header has already been read
	if (client->payload_length > 0) {
		if (read_available >= client->payload_length) {
			ipc_client_handle_command(client);
		}
		else {
			sway_log(L_DEBUG, "Too little data to read payload on IPC Client socket, waiting for more (%d < %d)", read_available, client->payload_length);
		}
		return 0;
	}

	if (read_available < ipc_header_size) {
		sway_log(L_DEBUG, "Too little data to read header on IPC Client socket, waiting for more (%d < %d)", read_available, ipc_header_size);
		return 0;
	}

	char buf[ipc_header_size];
	ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
	if (received == -1) {
		sway_log_errno(L_INFO, "Unable to receive header from IPC client");
		ipc_client_disconnect(client);
		return 0;
	}

	if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) {
		sway_log(L_DEBUG, "IPC header check failed");
		ipc_client_disconnect(client);
		return 0;
	}

	client->payload_length = *(uint32_t *)&buf[sizeof(ipc_magic)];
	client->current_command = (enum ipc_command_type) *(uint32_t *)&buf[sizeof(ipc_magic)+4];

	if (read_available - received >= client->payload_length) {
		ipc_client_handle_command(client);
	}

	return 0;
}
Exemple #17
0
void apply_output_config(struct output_config *oc, swayc_t *output) {
	if (oc && oc->width > 0 && oc->height > 0) {
		output->width = oc->width;
		output->height = oc->height;

		sway_log(L_DEBUG, "Set %s size to %ix%i", oc->name, oc->width, oc->height);
		struct wlc_size new_size = { .w = oc->width, .h = oc->height };
		wlc_output_set_resolution(output->handle, &new_size);
	}

	// Find position for it
	if (oc && oc->x != -1 && oc->y != -1) {
		sway_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
		output->x = oc->x;
		output->y = oc->y;
	} else {
		int x = 0;
		for (int i = 0; i < root_container.children->length; ++i) {
			swayc_t *c = root_container.children->items[i];
			if (c->type == C_OUTPUT) {
				if (c->width + c->x > x) {
					x = c->width + c->x;
				}
			}
		}
		output->x = x;
	}

	if (oc && oc->background) {
		int i;
		for (i = 0; i < root_container.children->length; ++i) {
			if (root_container.children->items[i] == output) {
				break;
			}
		}

		sway_log(L_DEBUG, "Setting background for output %d to %s", i, oc->background);

		size_t bufsize = 4;
		char output_id[bufsize];
		snprintf(output_id, bufsize, "%d", i);
		output_id[bufsize-1] = 0;

		char *const cmd[] = {
			"swaybg",
			output_id,
			oc->background,
			oc->background_option,
			NULL,
		};
		if (fork() == 0) {
			execvp(cmd[0], cmd);
		}
	}
}
Exemple #18
0
static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) {
	// save parent config
	const char *parent_config = config->current_config;

	char *full_path = strdup(path);
	int len = strlen(path);
	if (len >= 1 && path[0] != '/') {
		len = len + strlen(parent_dir) + 2;
		full_path = malloc(len * sizeof(char));
		if (!full_path) {
			sway_log(L_ERROR, "Unable to allocate full path to included config");
			return false;
		}
		snprintf(full_path, len, "%s/%s", parent_dir, path);
	}

	char *real_path = realpath(full_path, NULL);
	free(full_path);

	if (real_path == NULL) {
		sway_log(L_DEBUG, "%s not found.", path);
		return false;
	}

	// check if config has already been included
	int j;
	for (j = 0; j < config->config_chain->length; ++j) {
		char *old_path = config->config_chain->items[j];
		if (strcmp(real_path, old_path) == 0) {
			sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path);
			free(real_path);
			return false;
		}
	}

	config->current_config = real_path;
	list_add(config->config_chain, real_path);
	int index = config->config_chain->length - 1;

	if (!load_config(real_path, config)) {
		free(real_path);
		config->current_config = parent_config;
		list_del(config->config_chain, index);
		return false;
	}

	// restore current_config
	config->current_config = parent_config;
	return true;
}
Exemple #19
0
swayc_t *workspace_for_pid(pid_t pid) {
	int i;
	swayc_t *ws = NULL;
	struct pid_workspace *pw = NULL;

	sway_log(L_DEBUG, "looking for workspace for pid %d", pid);

	// leaving this here as it's useful for debugging
	// sway_log(L_DEBUG, "all pid_workspaces");
	// for (int k = 0; k < config->pid_workspaces->length; k++) {
	// 	pw = config->pid_workspaces->items[k];
	// 	sway_log(L_DEBUG, "pid %d workspace %s time_added %li", *pw->pid, pw->workspace, *pw->time_added);
	// }

	do {
		for (i = 0; i < config->pid_workspaces->length; i++) {
			pw = config->pid_workspaces->items[i];
			pid_t *pw_pid = pw->pid;

			if (pid == *pw_pid) {
				sway_log(L_DEBUG, "found pid_workspace for pid %d, workspace %s", pid, pw->workspace);
				break; // out of for loop
			}

			pw = NULL;
		}

		if (pw) {
			break; // out of do-while loop
		}

		pid = get_parent_pid(pid);
		// no sense in looking for matches for pid 0.
		// also, if pid == getpid(), that is the compositor's
		// pid, which definitely isn't helpful
	} while (pid > 0 && pid != getpid());

	if (pw) {
		ws = workspace_by_name(pw->workspace);

		if (!ws) {
			sway_log(L_DEBUG, "Creating workspace %s for pid %d because it disappeared", pw->workspace, pid);
			ws = workspace_create(pw->workspace);
		}

		list_del(config->pid_workspaces, i);
	}

	return ws;
}
Exemple #20
0
static struct panel_config *find_or_create_panel_config(struct wl_resource *resource) {
    for (int i = 0; i < desktop_shell.panels->length; i++) {
        struct panel_config *conf = desktop_shell.panels->items[i];
        if (conf->wl_resource == resource) {
            sway_log(L_DEBUG, "Found existing panel config for resource %p", resource);
            return conf;
        }
    }
    sway_log(L_DEBUG, "Creating panel config for resource %p", resource);
    struct panel_config *config = calloc(1, sizeof(struct panel_config));
    list_add(desktop_shell.panels, config);
    config->wl_resource = resource;
    return config;
}
Exemple #21
0
swayc_t *destroy_view(swayc_t *view) {
    if (view == NULL) {
        sway_log(L_DEBUG, "Warning: NULL passed into destroy_view");
        return NULL;
    }
    sway_log(L_DEBUG, "Destroying view '%p'", view);
    swayc_t *parent = view->parent;
    free_swayc(view);

    //Destroy empty containers
    if (parent->type == C_CONTAINER) {
        return destroy_container(parent);
    }
    return parent;
}
Exemple #22
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;
}
Exemple #23
0
swayc_t *new_output(wlc_handle handle) {
    const struct wlc_size* size = wlc_output_get_resolution(handle);
    const char *name = wlc_output_get_name(handle);
    sway_log(L_DEBUG, "Added output %u %s", (unsigned int)handle, name);

    swayc_t *output = new_swayc(C_OUTPUT);
    output->width = size->w;
    output->height = size->h;
    output->handle = handle;
    if (name) {
        output->name = strdup(name);
    }

    add_child(&root_container, output);

    //TODO something with this
    int total_width = 0;
    container_map(&root_container, add_output_widths, &total_width);

    //Create workspace
    char *ws_name = workspace_next_name();
    new_workspace(output, ws_name);
    free(ws_name);

    return output;
}
Exemple #24
0
int function_conversation(int num_msg, const struct pam_message **msg,
		struct pam_response **resp, void *appdata_ptr) {

	const char* msg_style_names[] = {
		NULL,
		"PAM_PROMPT_ECHO_OFF",
		"PAM_PROMPT_ECHO_ON",
		"PAM_ERROR_MSG",
		"PAM_TEXT_INFO",
	};

	/* PAM expects an array of responses, one for each message */
	struct pam_response *pam_reply = calloc(num_msg, sizeof(struct pam_response));
	*resp = pam_reply;

	for(int i=0; i<num_msg; ++i) {
		sway_log(L_DEBUG, "msg[%d]: (%s) %s", i,
				msg_style_names[msg[i]->msg_style],
				msg[i]->msg);

		switch (msg[i]->msg_style) {
		case PAM_PROMPT_ECHO_OFF:
		case PAM_PROMPT_ECHO_ON:
			pam_reply[i].resp = password;
			break;

		case PAM_ERROR_MSG:
		case PAM_TEXT_INFO:
			break;
		}
	}

	return PAM_SUCCESS;
}
Exemple #25
0
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
    switch(state) {
    case WLC_BIT_FULLSCREEN:
    {
        //I3 just lets it become fullscreen
        wlc_view_set_state(view,state,toggle);
        swayc_t *c = get_swayc_for_handle(view, &root_container);
        sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle);
        if (c) {
            arrange_windows(c->parent, -1, -1);
            //Set it as focused window for that workspace if its going
            //fullscreen
            if (toggle) {
                swayc_t *ws = c;
                while (ws->type != C_WORKSPACE) {
                    ws = ws->parent;
                }
                //Set ws focus to c
                focus_view_for(ws, c);
            }
        }
        break;
    }
    case WLC_BIT_MAXIMIZED:
    case WLC_BIT_RESIZING:
    case WLC_BIT_MOVING:
    case WLC_BIT_ACTIVATED:
        break;
    }
    return;
}
Exemple #26
0
static void handle_view_destroyed(wlc_handle handle) {
	sway_log(L_DEBUG, "Destroying window %lu", handle);
	swayc_t *view = get_swayc_for_handle(handle, &root_container);

	switch (wlc_view_get_type(handle)) {
	// regular view created regularly
	case 0:
	case WLC_BIT_MODAL:
		if (view) {
			swayc_t *parent = destroy_view(view);
			arrange_windows(parent, -1, -1);
		}
		break;
	// takes keyboard focus
	case WLC_BIT_OVERRIDE_REDIRECT:
		locked_view_focus = false;
		break;
	// Takes container focus
	case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
		locked_container_focus = false;
	case WLC_BIT_POPUP:
		break;
	}
	set_focused_container(get_focused_view(&root_container));
}
Exemple #27
0
// de-dupe pid_workspaces to ensure pid uniqueness
void pid_workspace_add(struct pid_workspace *pw) {
	struct pid_workspace *list_pw = NULL;
	struct timespec ts;
	time_t *now = malloc(sizeof(time_t));
	if (!now) {
		sway_log(L_ERROR, "Allocating time for pid_workspace failed");
		return;
	}

	pid_workspace_cleanup();

	// add current time to pw
	clock_gettime(CLOCK_MONOTONIC, &ts);
	*now = ts.tv_sec;

	pw->time_added = now;

	// work backwards through list and delete any entries that
	// have the same pid as that in our new pid_workspace
	for (int i = config->pid_workspaces->length - 1; i > -1; i--) {
		list_pw = config->pid_workspaces->items[i];

		if (pw->pid == list_pw->pid) {
			free_pid_workspace(config->pid_workspaces->items[i]);
			list_del(config->pid_workspaces, i);
		}
	}

	list_add(config->pid_workspaces, pw);
}
Exemple #28
0
static char *get_config_path(void) {
	static const char *config_paths[] = {
		"$HOME/.sway/config",
		"$XDG_CONFIG_HOME/sway/config",
		"$HOME/.i3/config",
		"$XDG_CONFIG_HOME/i3/config",
                FALLBACK_CONFIG_DIR "/config",
		"/etc/i3/config",
	};

	if (!getenv("XDG_CONFIG_HOME")) {
		char *home = getenv("HOME");
		char *config_home = malloc(strlen("home") + strlen("/.config") + 1);
		strcpy(config_home, home);
		strcat(config_home, "/.config");
		setenv("XDG_CONFIG_HOME", config_home, 1);
		sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
	}

	wordexp_t p;
	char *path;

	int i;
	for (i = 0; i < (int)(sizeof(config_paths) / sizeof(char *)); ++i) {
		if (wordexp(config_paths[i], &p, 0) == 0) {
			path = p.we_wordv[0];
			if (file_exists(path)) {
				return path;
			}
		}
	}

	return NULL; // Not reached
}
Exemple #29
0
static void handle_view_destroyed(wlc_handle handle) {
	sway_log(L_DEBUG, "Destroying window %lu", handle);
	swayc_t *view = get_swayc_for_handle(handle, &root_container);

	switch (wlc_view_get_type(handle)) {
	// regular view created regularly
	case 0:
	case WLC_BIT_MODAL:
	case WLC_BIT_POPUP:
		if (view) {
			swayc_t *parent = destroy_view(view);
			arrange_windows(parent, -1, -1);
		}
		break;
	// DMENU has this flag, and takes view_focus, but other things with this
	// flag dont
	case WLC_BIT_OVERRIDE_REDIRECT:
// 		locked_view_focus = false;
		break;
	case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
		locked_container_focus = false;
		break;
	}
	set_focused_container(get_focused_view(&root_container));
}
Exemple #30
0
struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) {
	const char *cmd_name = "tray_padding";
#ifndef ENABLE_TRAY
	return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command"
			"%s called, but sway was compiled without tray support",
			cmd_name, cmd_name);
#else
	struct cmd_results *error = NULL;
	if ((error = checkarg(argc, cmd_name, EXPECTED_AT_LEAST, 1))) {
		return error;
	}

	if (!config->current_bar) {
		return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined.");
	}

	if (argc == 1 || (argc == 2 && strcasecmp("px", argv[1]) == 0)) {
		char *inv;
		uint32_t padding = strtoul(argv[0], &inv, 10);
		if (*inv == '\0' || strcasecmp(inv, "px") == 0) {
			config->current_bar->tray_padding = padding;
			sway_log(L_DEBUG, "Enabling tray padding of %d px on bar: %s", padding, config->current_bar->id);
			return cmd_results_new(CMD_SUCCESS, NULL, NULL);
		}
	}
	return cmd_results_new(CMD_FAILURE, cmd_name,
		"Expected 'tray_padding <padding>[px]'");
#endif
}