mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Implement warp-mouse-to-focus
This commit is contained in:
committed by
Ivan Molodetskikh
parent
0c57815fbf
commit
741bee461c
@@ -69,6 +69,8 @@ pub struct Input {
|
||||
pub touch: Touch,
|
||||
#[knuffel(child)]
|
||||
pub disable_power_key_handling: bool,
|
||||
#[knuffel(child)]
|
||||
pub warp_mouse_to_focus: bool,
|
||||
}
|
||||
|
||||
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
|
||||
@@ -1592,6 +1594,8 @@ mod tests {
|
||||
}
|
||||
|
||||
disable-power-key-handling
|
||||
|
||||
warp-mouse-to-focus
|
||||
}
|
||||
|
||||
output "eDP-1" {
|
||||
@@ -1731,6 +1735,7 @@ mod tests {
|
||||
map_to_output: Some("eDP-1".to_owned()),
|
||||
},
|
||||
disable_power_key_handling: true,
|
||||
warp_mouse_to_focus: true,
|
||||
},
|
||||
outputs: vec![Output {
|
||||
off: false,
|
||||
|
||||
@@ -67,6 +67,9 @@ input {
|
||||
// Uncomment this if you would like to configure the power button elsewhere
|
||||
// (i.e. logind.conf).
|
||||
// disable-power-key-handling
|
||||
|
||||
// Uncomment this to make the mouse warp to the center of newly focused windows.
|
||||
// warp-mouse-to-focus
|
||||
}
|
||||
|
||||
// You can configure outputs by their name, which you can find
|
||||
|
||||
+78
-16
@@ -411,139 +411,166 @@ impl State {
|
||||
}
|
||||
Action::MoveColumnLeft => {
|
||||
self.niri.layout.move_left();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveColumnRight => {
|
||||
self.niri.layout.move_right();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveColumnToFirst => {
|
||||
self.niri.layout.move_column_to_first();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveColumnToLast => {
|
||||
self.niri.layout.move_column_to_last();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowDown => {
|
||||
self.niri.layout.move_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowUp => {
|
||||
self.niri.layout.move_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowDownOrToWorkspaceDown => {
|
||||
self.niri.layout.move_down_or_to_workspace_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowUpOrToWorkspaceUp => {
|
||||
self.niri.layout.move_up_or_to_workspace_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::ConsumeOrExpelWindowLeft => {
|
||||
self.niri.layout.consume_or_expel_window_left();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::ConsumeOrExpelWindowRight => {
|
||||
self.niri.layout.consume_or_expel_window_right();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusColumnLeft => {
|
||||
self.niri.layout.focus_left();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusColumnRight => {
|
||||
self.niri.layout.focus_right();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusColumnFirst => {
|
||||
self.niri.layout.focus_column_first();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusColumnLast => {
|
||||
self.niri.layout.focus_column_last();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowDown => {
|
||||
self.niri.layout.focus_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowUp => {
|
||||
self.niri.layout.focus_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowOrWorkspaceDown => {
|
||||
self.niri.layout.focus_window_or_workspace_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowOrWorkspaceUp => {
|
||||
self.niri.layout.focus_window_or_workspace_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowToWorkspaceDown => {
|
||||
self.niri.layout.move_to_workspace_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowToWorkspaceUp => {
|
||||
self.niri.layout.move_to_workspace_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowToWorkspace(idx) => {
|
||||
let idx = idx.saturating_sub(1) as usize;
|
||||
self.niri.layout.move_to_workspace(idx);
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveColumnToWorkspaceDown => {
|
||||
self.niri.layout.move_column_to_workspace_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveColumnToWorkspaceUp => {
|
||||
self.niri.layout.move_column_to_workspace_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveColumnToWorkspace(idx) => {
|
||||
let idx = idx.saturating_sub(1) as usize;
|
||||
self.niri.layout.move_column_to_workspace(idx);
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWorkspaceDown => {
|
||||
self.niri.layout.switch_workspace_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWorkspaceUp => {
|
||||
self.niri.layout.switch_workspace_up();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWorkspace(idx) => {
|
||||
let idx = idx.saturating_sub(1) as usize;
|
||||
self.niri.layout.switch_workspace(idx);
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
@@ -559,11 +586,14 @@ impl State {
|
||||
}
|
||||
Action::ConsumeWindowIntoColumn => {
|
||||
self.niri.layout.consume_into_column();
|
||||
// This does not cause immediate focus or window size change, so warping mouse to
|
||||
// focus won't do anything here.
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::ExpelWindowFromColumn => {
|
||||
self.niri.layout.expel_from_column();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
@@ -581,81 +611,105 @@ impl State {
|
||||
Action::FocusMonitorLeft => {
|
||||
if let Some(output) = self.niri.output_left() {
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::FocusMonitorRight => {
|
||||
if let Some(output) = self.niri.output_right() {
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::FocusMonitorDown => {
|
||||
if let Some(output) = self.niri.output_down() {
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::FocusMonitorUp => {
|
||||
if let Some(output) = self.niri.output_up() {
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWindowToMonitorLeft => {
|
||||
if let Some(output) = self.niri.output_left() {
|
||||
self.niri.layout.move_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWindowToMonitorRight => {
|
||||
if let Some(output) = self.niri.output_right() {
|
||||
self.niri.layout.move_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWindowToMonitorDown => {
|
||||
if let Some(output) = self.niri.output_down() {
|
||||
self.niri.layout.move_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWindowToMonitorUp => {
|
||||
if let Some(output) = self.niri.output_up() {
|
||||
self.niri.layout.move_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveColumnToMonitorLeft => {
|
||||
if let Some(output) = self.niri.output_left() {
|
||||
self.niri.layout.move_column_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveColumnToMonitorRight => {
|
||||
if let Some(output) = self.niri.output_right() {
|
||||
self.niri.layout.move_column_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveColumnToMonitorDown => {
|
||||
if let Some(output) = self.niri.output_down() {
|
||||
self.niri.layout.move_column_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveColumnToMonitorUp => {
|
||||
if let Some(output) = self.niri.output_up() {
|
||||
self.niri.layout.move_column_to_output(&output);
|
||||
self.niri.layout.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::SetColumnWidth(change) => {
|
||||
@@ -672,25 +726,33 @@ impl State {
|
||||
Action::MoveWorkspaceToMonitorLeft => {
|
||||
if let Some(output) = self.niri.output_left() {
|
||||
self.niri.layout.move_workspace_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWorkspaceToMonitorRight => {
|
||||
if let Some(output) = self.niri.output_right() {
|
||||
self.niri.layout.move_workspace_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWorkspaceToMonitorDown => {
|
||||
if let Some(output) = self.niri.output_down() {
|
||||
self.niri.layout.move_workspace_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveWorkspaceToMonitorUp => {
|
||||
if let Some(output) = self.niri.output_up() {
|
||||
self.niri.layout.move_workspace_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,6 +583,14 @@ impl<W: LayoutElement> Monitor<W> {
|
||||
self.clean_up_workspaces();
|
||||
}
|
||||
|
||||
/// Returns the geometry of the active tile relative to and clamped to the output.
|
||||
///
|
||||
/// During animations, assumes the final view position.
|
||||
pub fn active_tile_visual_rectangle(&self) -> Option<Rectangle<i32, Logical>> {
|
||||
// FIXME: switch gesture.
|
||||
self.active_workspace_ref().active_tile_visual_rectangle()
|
||||
}
|
||||
|
||||
pub fn window_under(
|
||||
&self,
|
||||
pos_within_output: Point<f64, Logical>,
|
||||
|
||||
@@ -181,6 +181,15 @@ impl OutputId {
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewOffsetAdjustment {
|
||||
pub fn target_view_offset(&self) -> f64 {
|
||||
match self {
|
||||
ViewOffsetAdjustment::Animation(anim) => anim.to(),
|
||||
ViewOffsetAdjustment::Gesture(gesture) => gesture.current_view_offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ColumnWidth {
|
||||
fn resolve(self, options: &Options, view_width: i32) -> i32 {
|
||||
match self {
|
||||
@@ -1124,6 +1133,31 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
first.chain(rest)
|
||||
}
|
||||
|
||||
fn active_column_ref(&self) -> Option<&Column<W>> {
|
||||
if self.columns.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(&self.columns[self.active_column_idx])
|
||||
}
|
||||
|
||||
/// Returns the geometry of the active tile relative to and clamped to the view.
|
||||
///
|
||||
/// During animations, assumes the final view position.
|
||||
pub fn active_tile_visual_rectangle(&self) -> Option<Rectangle<i32, Logical>> {
|
||||
let col = self.active_column_ref()?;
|
||||
let view_pos = self
|
||||
.view_offset_adj
|
||||
.as_ref()
|
||||
.map_or(self.view_offset, |adj| adj.target_view_offset() as i32);
|
||||
|
||||
let tile_pos = Point::from((-view_pos, col.tile_y(col.active_tile_idx)));
|
||||
let tile_size = col.active_tile_ref().tile_size();
|
||||
let tile_rect = Rectangle::from_loc_and_size(tile_pos, tile_size);
|
||||
|
||||
let view = Rectangle::from_loc_and_size((0, 0), self.view_size);
|
||||
view.intersection(tile_rect)
|
||||
}
|
||||
|
||||
pub fn window_under(
|
||||
&self,
|
||||
pos: Point<f64, Logical>,
|
||||
@@ -2010,6 +2044,10 @@ impl<W: LayoutElement> Column<W> {
|
||||
pos
|
||||
})
|
||||
}
|
||||
|
||||
fn active_tile_ref(&self) -> &Tile<W> {
|
||||
&self.tiles[self.active_tile_idx]
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_new_view_offset(
|
||||
|
||||
+78
-2
@@ -112,7 +112,7 @@ use crate::ui::hotkey_overlay::HotkeyOverlay;
|
||||
use crate::ui::screenshot_ui::{ScreenshotUi, ScreenshotUiRenderElement};
|
||||
use crate::utils::spawning::CHILD_ENV;
|
||||
use crate::utils::{
|
||||
center, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
|
||||
center, center_f64, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
|
||||
};
|
||||
use crate::window::Unmapped;
|
||||
use crate::{animation, niri_render_elements};
|
||||
@@ -197,7 +197,6 @@ pub struct Niri {
|
||||
// popup grabs are active (which means the real keyboard focus is on a popup descending from
|
||||
// this toplevel surface).
|
||||
pub keyboard_focus: Option<WlSurface>,
|
||||
|
||||
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
||||
pub is_fdo_idle_inhibited: Arc<AtomicBool>,
|
||||
|
||||
@@ -314,6 +313,11 @@ struct SurfaceFrameThrottlingState {
|
||||
last_sent_at: RefCell<Option<(Output, u32)>>,
|
||||
}
|
||||
|
||||
pub enum CenterCoords {
|
||||
Seperately,
|
||||
Both,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WindowOffscreenId(pub RefCell<Option<Id>>);
|
||||
|
||||
@@ -401,6 +405,78 @@ impl State {
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
|
||||
/// Moves cursor within the specified rectangle, only adjusting coordinates if needed.
|
||||
fn move_cursor_to_rect(&mut self, rect: Rectangle<f64, Logical>, mode: CenterCoords) -> bool {
|
||||
let pointer = &self.niri.seat.get_pointer().unwrap();
|
||||
let cur_loc = pointer.current_location();
|
||||
let x_in_bound = cur_loc.x >= rect.loc.x && cur_loc.x <= rect.loc.x + rect.size.w;
|
||||
let y_in_bound = cur_loc.y >= rect.loc.y && cur_loc.y <= rect.loc.y + rect.size.h;
|
||||
|
||||
let p = match mode {
|
||||
CenterCoords::Seperately => {
|
||||
if x_in_bound && y_in_bound {
|
||||
return false;
|
||||
} else if y_in_bound {
|
||||
// adjust x
|
||||
Point::from((rect.loc.x + rect.size.w / 2.0, cur_loc.y))
|
||||
} else if x_in_bound {
|
||||
// adjust y
|
||||
Point::from((cur_loc.x, rect.loc.y + rect.size.h / 2.0))
|
||||
} else {
|
||||
// adjust x and y
|
||||
center_f64(rect)
|
||||
}
|
||||
}
|
||||
CenterCoords::Both => {
|
||||
if x_in_bound && y_in_bound {
|
||||
return false;
|
||||
} else {
|
||||
// adjust x and y
|
||||
center_f64(rect)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.move_cursor(p);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn move_cursor_to_focused_tile(&mut self, mode: CenterCoords) -> bool {
|
||||
let Some(output) = self.niri.layout.active_output() else {
|
||||
return false;
|
||||
};
|
||||
let output = output.clone();
|
||||
let monitor = self.niri.layout.monitor_for_output(&output).unwrap();
|
||||
|
||||
let mut rv = false;
|
||||
let rect = monitor.active_tile_visual_rectangle();
|
||||
|
||||
if let Some(rect) = rect {
|
||||
let output_geo = self.niri.global_space.output_geometry(&output).unwrap();
|
||||
let mut rect = rect;
|
||||
rect.loc += output_geo.loc;
|
||||
rv = self.move_cursor_to_rect(rect.to_f64(), mode);
|
||||
}
|
||||
|
||||
rv
|
||||
}
|
||||
|
||||
pub fn maybe_warp_cursor_to_focus(&mut self) -> bool {
|
||||
if !self.niri.config.borrow().input.warp_mouse_to_focus {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.move_cursor_to_focused_tile(CenterCoords::Seperately)
|
||||
}
|
||||
|
||||
pub fn maybe_warp_cursor_to_focus_centered(&mut self) -> bool {
|
||||
if !self.niri.config.borrow().input.warp_mouse_to_focus {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.move_cursor_to_focused_tile(CenterCoords::Both)
|
||||
}
|
||||
|
||||
pub fn refresh_pointer_focus(&mut self) {
|
||||
let _span = tracy_client::span!("Niri::refresh_pointer_focus");
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@ pub fn center(rect: Rectangle<i32, Logical>) -> Point<i32, Logical> {
|
||||
rect.loc + rect.size.downscale(2).to_point()
|
||||
}
|
||||
|
||||
pub fn center_f64(rect: Rectangle<f64, Logical>) -> Point<f64, Logical> {
|
||||
rect.loc + rect.size.downscale(2.0).to_point()
|
||||
}
|
||||
|
||||
pub fn output_size(output: &Output) -> Size<i32, Logical> {
|
||||
let output_scale = output.current_scale().integer_scale();
|
||||
let output_transform = output.current_transform();
|
||||
|
||||
Reference in New Issue
Block a user