menu: Respect output bounds

This commit is contained in:
Victoria Brekenfeld 2023-12-08 17:52:44 +00:00 committed by Victoria Brekenfeld
parent 02a6290067
commit 131ab8fe9e
2 changed files with 90 additions and 10 deletions

View file

@ -158,21 +158,27 @@ where
shell: &mut Shell<'_, Message>,
viewport: &Rectangle,
) -> event::Status {
let is_over = cursor.is_over(layout.bounds());
let mut bounds = layout.bounds();
// fix padding 1 and event... don't ask.
bounds.x -= 1.;
bounds.width += 2.;
let is_over = cursor.is_over(bounds);
let widget_state = state.state.downcast_mut::<State>();
match event {
Event::Mouse(mouse::Event::CursorEntered)
| Event::Mouse(mouse::Event::CursorMoved { .. })
if is_over && !widget_state.cursor_over =>
{
shell.publish(Message::cursor_entered(self.idx, layout.bounds()));
shell.publish(Message::cursor_entered(self.idx, bounds));
widget_state.cursor_over = true;
}
Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Mouse(mouse::Event::CursorLeft)
if !is_over && widget_state.cursor_over =>
{
shell.publish(Message::cursor_left(self.idx, layout.bounds()));
shell.publish(Message::cursor_left(self.idx, bounds));
widget_state.cursor_over = false;
}
_ => {}

View file

@ -42,7 +42,7 @@ use smithay::{
Seat,
},
output::Output,
utils::{Logical, Point, Scale, Size, Transform},
utils::{Logical, Point, Rectangle, Scale, Size, Transform},
wayland::seat::WaylandFocus,
};
use tracing::warn;
@ -60,7 +60,7 @@ use crate::{
state::{BackendData, Common, State},
utils::{
iced::{IcedElement, Program},
prelude::{Global, PointGlobalExt, PointLocalExt, SeatExt},
prelude::{Global, OutputExt, PointGlobalExt, PointLocalExt, SeatExt, SizeExt},
},
};
@ -239,22 +239,69 @@ impl Program for ContextMenu {
if let Some(grab_state) = &*grab_state {
let mut elements = grab_state.elements.lock().unwrap();
let mut position = elements.last().unwrap().position;
position.x += bounds.width.ceil() as i32;
position.y += bounds.y.ceil() as i32;
let position = elements.last().unwrap().position;
let element = IcedElement::new(
ContextMenu::new(items),
Size::default(),
state.common.event_loop_handle.clone(),
state.common.theme.clone(),
);
let min_size = element.minimum_size();
element.with_program(|p| {
*p.row_width.lock().unwrap() = Some(min_size.w as f32);
});
element.resize(min_size);
element.output_enter(&seat.active_output(), element.bbox());
let output = seat.active_output();
let position = [
// to the right -> down
Rectangle::from_loc_and_size(
position
+ Point::from((
bounds.width.ceil() as i32,
bounds.y.ceil() as i32,
)),
min_size.as_global(),
),
// to the right -> up
Rectangle::from_loc_and_size(
position
+ Point::from((
bounds.width.ceil() as i32,
bounds.y.ceil() as i32 + bounds.height.ceil() as i32
- min_size.h,
)),
min_size.as_global(),
),
// to the left -> down
Rectangle::from_loc_and_size(
position + Point::from((-min_size.w, bounds.y.ceil() as i32)),
min_size.as_global(),
),
// to the left -> up
Rectangle::from_loc_and_size(
position
+ Point::from((
-min_size.w,
bounds.y.ceil() as i32 + bounds.height.ceil() as i32
- min_size.h,
)),
min_size.as_global(),
),
]
.iter()
.rev() // preference of max_by_key is backwards
.max_by_key(|rect| {
output
.geometry()
.intersection(**rect)
.map(|rect| rect.size.w * rect.size.h)
})
.unwrap()
.loc;
element.output_enter(&output, element.bbox());
elements.push(Element {
iced: element,
@ -611,7 +658,34 @@ impl MenuGrab {
});
element.resize(min_size);
element.output_enter(&seat.active_output(), element.bbox());
let output = seat.active_output();
let position = [
Rectangle::from_loc_and_size(position, min_size.as_global()), // normal
Rectangle::from_loc_and_size(
position - Point::from((min_size.w, 0)),
min_size.as_global(),
), // flipped left
Rectangle::from_loc_and_size(
position - Point::from((0, min_size.h)),
min_size.as_global(),
), // flipped up
Rectangle::from_loc_and_size(
position - Point::from((min_size.w, min_size.h)),
min_size.as_global(),
), // flipped left & up
]
.iter()
.rev() // preference of max_by_key is backwards
.max_by_key(|rect| {
output
.geometry()
.intersection(**rect)
.map(|rect| rect.size.w * rect.size.h)
})
.unwrap()
.loc;
element.output_enter(&output, element.bbox());
let elements = Arc::new(Mutex::new(vec![Element {
iced: element,