예제 #1
0
swayc_t *focus_pointer(void) {
    swayc_t *focused = get_focused_container(&root_container);
    if (!(wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) {
        swayc_t *pointer = find_container(&root_container, pointer_test, &mouse_origin);
        if (pointer && focused != pointer) {
            unfocus_all(&root_container);
            focus_view(pointer);
        } else if (!focused) {
            focus_view(active_workspace);
        }
        focused = pointer;
    }
    return focused;
}
예제 #2
0
파일: loliwm.c 프로젝트: holomorph/loliwm
static void
relayout(struct wlc_space *space)
{
   if (!space)
      return;

   struct wl_list *views;
   if (!(views = wlc_space_get_userdata(space)))
      return;

   uint32_t rwidth, rheight;
   struct wlc_output *output = wlc_space_get_output(space);
   wlc_output_get_resolution(output, &rwidth, &rheight);

   struct wlc_view *v;
   uint32_t count = 0;
   wlc_view_for_each_user(v, views)
      if (is_tiled(v)) ++count;

   bool toggle = false;
   uint32_t y = 0, height = rheight / (count > 1 ? count - 1 : 1);
   uint32_t fheight = (rheight > height * (count - 1) ? height + (rheight - height * (count - 1)) : height);
   wlc_view_for_each_user(v, views) {
      if (wlc_view_get_state(v) & WLC_BIT_FULLSCREEN) {
         wlc_view_resize(v, rwidth, rheight);
         wlc_view_position(v, 0, 0);
      }

      if (wlc_view_get_type(v) & WLC_BIT_SPLASH)
         wlc_view_position(v, rwidth * 0.5 - wlc_view_get_width(v) * 0.5, rheight * 0.5 - wlc_view_get_height(v) * 0.5);

      struct wlc_view *parent;
      if (is_managed(v) && !is_or(v) && (parent = wlc_view_get_parent(v)))
         layout_parent(v, parent, wlc_view_get_width(v), wlc_view_get_height(v));

      if (!is_tiled(v))
         continue;

      uint32_t slave = rwidth * loliwm.cut;
      wlc_view_set_state(v, WLC_BIT_MAXIMIZED, true);
      wlc_view_resize(v, (count > 1 ? (toggle ? slave : rwidth - slave) : rwidth), (toggle ? (y == 0 ? fheight : height) : rheight));
      wlc_view_position(v, (toggle ? rwidth - slave : 0), y);

      if (toggle)
         y += (y == 0 ? fheight : height);

      toggle = true;
   }
}
예제 #3
0
static bool handle_view_created(wlc_handle handle) {
    swayc_t *focused = get_focused_container(&root_container);
    uint32_t type = wlc_view_get_type(handle);
    // If override_redirect/unmanaged/popup/modal/splach
    if (type) {
        sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type);
        wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
        if (type & WLC_BIT_UNMANAGED) {
            return true;
        }
        // For things like Dmenu
        if (type & WLC_BIT_OVERRIDE_REDIRECT) {
            override_redirect = true;
            wlc_view_focus(handle);
        }

        // Float popups
        if (type & WLC_BIT_POPUP) {
            swayc_t *view = new_floating_view(handle);
            wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, false);
            focus_view(view);
            arrange_windows(active_workspace, -1, -1);
        }
    } else {
        swayc_t *view = new_view(focused, handle);
        //Set maximize flag for windows.
        //TODO: floating windows have this unset
        wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
        unfocus_all(&root_container);
        focus_view(view);
        arrange_windows(view->parent, -1, -1);
    }
    if (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
        unfocus_all(&root_container);
        focus_view(focused);
        arrange_windows(focused, -1, -1);
    }
    return true;
}
예제 #4
0
파일: handlers.c 프로젝트: illblew/sway
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;
	}
예제 #5
0
파일: handlers.c 프로젝트: illblew/sway
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;
}
예제 #6
0
파일: loliwm.c 프로젝트: holomorph/loliwm
static bool
is_tiled(struct wlc_view *view)
{
   uint32_t state = wlc_view_get_state(view);
   return !(state & WLC_BIT_FULLSCREEN) && !wlc_view_get_parent(view) && is_managed(view) && !is_or(view) && !is_modal(view);
}
예제 #7
0
파일: loliwm.c 프로젝트: holomorph/loliwm
static bool
is_or(struct wlc_view *view)
{
   return (wlc_view_get_type(view) & WLC_BIT_OVERRIDE_REDIRECT) || (wlc_view_get_state(view) & BIT_BEMENU);
}
예제 #8
0
void arrange_windows(swayc_t *container, int width, int height) {
	int i;
	if (width == -1 || height == -1) {
		sway_log(L_DEBUG, "Arranging layout for %p", container);
		width = container->width;
		height = container->height;
	}

	int x = 0, y = 0;
	switch (container->type) {
	case C_ROOT:
		for (i = 0; i < container->children->length; ++i) {
			swayc_t *child = container->children->items[i];
			sway_log(L_DEBUG, "Arranging output at %d", x);
			child->x = x;
			child->y = y;
			arrange_windows(child, -1, -1);
			// Removed for now because wlc works with relative positions
			// Addition can be reconsidered once wlc positions are changed
			// x += child->width;
		}
		return;
	case C_OUTPUT:
		container->width = width;
		container->height = height;
		// These lines make x/y negative and result in stuff glitching out
		// Their addition can be reconsidered once wlc positions are changed
		// x -= container->x;
		// y -= container->y;
		for (i = 0; i < container->children->length; ++i) {
			swayc_t *child = container->children->items[i];
			child->x = x + container->gaps;
			child->y = y + container->gaps;
			child->width = width - container->gaps * 2;
			child->height = height - container->gaps * 2;
			sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y);
			arrange_windows(child, -1, -1);
		}
		return;
	case C_VIEW:
		{
			struct wlc_geometry geometry = {
				.origin = {
					.x = container->x + container->gaps,
					.y = container->y + container->gaps
				},
				.size = {
					.w = width - container->gaps * 2,
					.h = height - container->gaps * 2
				}
			};
			if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) {
				swayc_t *parent = container;
				while (parent->type != C_OUTPUT) {
					parent = parent->parent;
				}
				geometry.origin.x = 0;
				geometry.origin.y = 0;
				geometry.size.w = parent->width;
				geometry.size.h = parent->height;
				wlc_view_set_geometry(container->handle, 0, &geometry);
				wlc_view_bring_to_front(container->handle);
			} else {
				wlc_view_set_geometry(container->handle, 0, &geometry);
				container->width = width;
				container->height = height;
			}
			sway_log(L_DEBUG, "Set view to %d x %d @ %d, %d", geometry.size.w, geometry.size.h,
					geometry.origin.x, geometry.origin.y);
		}
		return;
	default:
		container->width = width;
		container->height = height;
		break;
	}