mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Implement clicking on tab to switch
This commit is contained in:
+5
-2
@@ -466,7 +466,10 @@ pub enum HitType {
|
|||||||
/// The hit can activate a window, but it is not in the input region so cannot send events.
|
/// The hit can activate a window, but it is not in the input region so cannot send events.
|
||||||
///
|
///
|
||||||
/// For example, this could be clicking on a tile border outside the window.
|
/// For example, this could be clicking on a tile border outside the window.
|
||||||
Activate,
|
Activate {
|
||||||
|
/// Whether the hit was on the tab indicator.
|
||||||
|
is_tab_indicator: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: LayoutElement> InteractiveMoveState<W> {
|
impl<W: LayoutElement> InteractiveMoveState<W> {
|
||||||
@@ -515,7 +518,7 @@ impl HitType {
|
|||||||
pub fn offset_win_pos(mut self, offset: Point<f64, Logical>) -> Self {
|
pub fn offset_win_pos(mut self, offset: Point<f64, Logical>) -> Self {
|
||||||
match &mut self {
|
match &mut self {
|
||||||
HitType::Input { win_pos } => *win_pos += offset,
|
HitType::Input { win_pos } => *win_pos += offset,
|
||||||
HitType::Activate => (),
|
HitType::Activate { .. } => (),
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-1
@@ -14,7 +14,7 @@ use super::insert_hint_element::{InsertHintElement, InsertHintRenderElement};
|
|||||||
use super::tab_indicator::{TabIndicator, TabIndicatorRenderElement, TabInfo};
|
use super::tab_indicator::{TabIndicator, TabIndicatorRenderElement, TabInfo};
|
||||||
use super::tile::{Tile, TileRenderElement, TileRenderSnapshot};
|
use super::tile::{Tile, TileRenderElement, TileRenderSnapshot};
|
||||||
use super::workspace::{InteractiveResize, ResolvedSize};
|
use super::workspace::{InteractiveResize, ResolvedSize};
|
||||||
use super::{ConfigureIntent, InteractiveResizeData, LayoutElement, Options, RemovedTile};
|
use super::{ConfigureIntent, HitType, InteractiveResizeData, LayoutElement, Options, RemovedTile};
|
||||||
use crate::animation::{Animation, Clock};
|
use crate::animation::{Animation, Clock};
|
||||||
use crate::input::swipe_tracker::SwipeTracker;
|
use crate::input::swipe_tracker::SwipeTracker;
|
||||||
use crate::niri_render_elements;
|
use crate::niri_render_elements;
|
||||||
@@ -2645,6 +2645,51 @@ impl<W: LayoutElement> ScrollingSpace<W> {
|
|||||||
rv
|
rv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<(&W, HitType)> {
|
||||||
|
// This matches self.tiles_with_render_positions().
|
||||||
|
let scale = self.scale;
|
||||||
|
let view_off = Point::from((-self.view_pos(), 0.));
|
||||||
|
for (col, col_x) in self.columns_in_render_order() {
|
||||||
|
let col_off = Point::from((col_x, 0.));
|
||||||
|
let col_render_off = col.render_offset();
|
||||||
|
|
||||||
|
// Hit the tab indicator.
|
||||||
|
if col.display_mode == ColumnDisplay::Tabbed && !col.is_fullscreen {
|
||||||
|
let col_pos = view_off + col_off + col_render_off;
|
||||||
|
let col_pos = col_pos.to_physical_precise_round(scale).to_logical(scale);
|
||||||
|
|
||||||
|
if let Some(idx) = col.tab_indicator.hit(
|
||||||
|
col.tab_indicator_area(),
|
||||||
|
col.tiles.len(),
|
||||||
|
scale,
|
||||||
|
pos - col_pos,
|
||||||
|
) {
|
||||||
|
let hit = HitType::Activate {
|
||||||
|
is_tab_indicator: true,
|
||||||
|
};
|
||||||
|
return Some((col.tiles[idx].window(), hit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tile, tile_off, visible) in col.tiles_in_render_order() {
|
||||||
|
if !visible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tile_pos =
|
||||||
|
view_off + col_off + col_render_off + tile_off + tile.render_offset();
|
||||||
|
// Round to physical pixels.
|
||||||
|
let tile_pos = tile_pos.to_physical_precise_round(scale).to_logical(scale);
|
||||||
|
|
||||||
|
if let Some(rv) = HitType::hit_tile(tile, tile_pos, pos) {
|
||||||
|
return Some(rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn view_offset_gesture_begin(&mut self, is_touchpad: bool) {
|
pub fn view_offset_gesture_begin(&mut self, is_touchpad: bool) {
|
||||||
if self.columns.is_empty() {
|
if self.columns.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -182,6 +182,27 @@ impl TabIndicator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hit(
|
||||||
|
&self,
|
||||||
|
area: Rectangle<f64, Logical>,
|
||||||
|
tab_count: usize,
|
||||||
|
scale: f64,
|
||||||
|
point: Point<f64, Logical>,
|
||||||
|
) -> Option<usize> {
|
||||||
|
if self.config.off {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = tab_count;
|
||||||
|
if self.config.hide_when_single_tab && count == 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tab_rects(area, count, scale)
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(idx, rect)| rect.contains(point).then_some(idx))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render(
|
pub fn render(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut impl NiriRenderer,
|
renderer: &mut impl NiriRenderer,
|
||||||
|
|||||||
+3
-1
@@ -658,7 +658,9 @@ impl<W: LayoutElement> Tile<W> {
|
|||||||
let win_pos = self.buf_loc();
|
let win_pos = self.buf_loc();
|
||||||
Some(HitType::Input { win_pos })
|
Some(HitType::Input { win_pos })
|
||||||
} else if self.is_in_activation_region(point) {
|
} else if self.is_in_activation_region(point) {
|
||||||
Some(HitType::Activate)
|
Some(HitType::Activate {
|
||||||
|
is_tab_indicator: false,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-6
@@ -1475,14 +1475,18 @@ impl<W: LayoutElement> Workspace<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<(&W, HitType)> {
|
pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<(&W, HitType)> {
|
||||||
self.tiles_with_render_positions()
|
// This logic is consistent with tiles_with_render_positions().
|
||||||
.find_map(|(tile, tile_pos, visible)| {
|
if self.is_floating_visible() {
|
||||||
if !visible {
|
if let Some(rv) = self
|
||||||
return None;
|
.floating
|
||||||
|
.tiles_with_render_positions()
|
||||||
|
.find_map(|(tile, tile_pos)| HitType::hit_tile(tile, tile_pos, pos))
|
||||||
|
{
|
||||||
|
return Some(rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HitType::hit_tile(tile, tile_pos, pos)
|
self.scrolling.window_under(pos)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize_edges_under(&self, pos: Point<f64, Logical>) -> Option<ResizeEdge> {
|
pub fn resize_edges_under(&self, pos: Point<f64, Logical>) -> Option<ResizeEdge> {
|
||||||
|
|||||||
+11
-1
@@ -5060,7 +5060,17 @@ impl Niri {
|
|||||||
|
|
||||||
if let Some(window) = &new_focus.window {
|
if let Some(window) = &new_focus.window {
|
||||||
if current_focus.window.as_ref() != Some(window) {
|
if current_focus.window.as_ref() != Some(window) {
|
||||||
let (window, _) = window;
|
let (window, hit) = window;
|
||||||
|
|
||||||
|
// Don't trigger focus-follows-mouse over the tab indicator.
|
||||||
|
if matches!(
|
||||||
|
hit,
|
||||||
|
HitType::Activate {
|
||||||
|
is_tab_indicator: true
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if !self.layout.should_trigger_focus_follows_mouse_on(window) {
|
if !self.layout.should_trigger_focus_follows_mouse_on(window) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user