state: Move shell behind RwLock
This commit is contained in:
parent
647deb81f1
commit
5d5a510691
45 changed files with 2657 additions and 2097 deletions
|
|
@ -11,8 +11,9 @@ use crate::{
|
|||
utils::prelude::*,
|
||||
wayland::{
|
||||
handlers::screencopy::{submit_buffer, FrameHolder, SessionData},
|
||||
protocols::screencopy::{
|
||||
FailureReason, Frame as ScreencopyFrame, Session as ScreencopySession,
|
||||
protocols::{
|
||||
screencopy::{FailureReason, Frame as ScreencopyFrame, Session as ScreencopySession},
|
||||
workspace::WorkspaceUpdateGuard,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -76,6 +77,7 @@ use smithay::{
|
|||
relative_pointer::RelativePointerManagerState,
|
||||
seat::WaylandFocus,
|
||||
shm::{shm_format_to_fourcc, with_buffer_contents},
|
||||
xdg_activation::XdgActivationState,
|
||||
},
|
||||
};
|
||||
use tracing::{error, info, trace, warn};
|
||||
|
|
@ -202,7 +204,7 @@ pub fn init_backend(
|
|||
state.backend.kms().input_devices.remove(device.name());
|
||||
}
|
||||
state.process_input_event(event, true);
|
||||
for output in state.common.shell.outputs() {
|
||||
for output in state.common.shell.read().unwrap().outputs() {
|
||||
if let Err(err) = state.backend.kms().schedule_render(
|
||||
&state.common.event_loop_handle,
|
||||
output,
|
||||
|
|
@ -326,9 +328,13 @@ pub fn init_backend(
|
|||
state.common.config.read_outputs(
|
||||
&mut state.common.output_configuration_state,
|
||||
&mut state.backend,
|
||||
&mut state.common.shell,
|
||||
&mut state.common.shell.write().unwrap(),
|
||||
&state.common.event_loop_handle,
|
||||
&mut state.common.workspace_state.update(),
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
state.common.refresh();
|
||||
|
||||
for surface in state
|
||||
.backend
|
||||
.kms()
|
||||
|
|
@ -339,7 +345,7 @@ pub fn init_backend(
|
|||
surface.scheduled = false;
|
||||
surface.pending = false;
|
||||
}
|
||||
for output in state.common.shell.outputs() {
|
||||
for output in state.common.shell.read().unwrap().outputs() {
|
||||
if let Err(err) = state.backend.kms().schedule_render(
|
||||
&state.common.event_loop_handle,
|
||||
output,
|
||||
|
|
@ -601,7 +607,7 @@ impl State {
|
|||
|
||||
let outputs = device.enumerate_surfaces()?.added; // There are no removed outputs on newly added devices
|
||||
let mut wl_outputs = Vec::new();
|
||||
let mut w = self.common.shell.global_space().size.w;
|
||||
let mut w = self.common.shell.read().unwrap().global_space().size.w;
|
||||
{
|
||||
let backend = self.backend.kms();
|
||||
backend
|
||||
|
|
@ -701,9 +707,12 @@ impl State {
|
|||
self.common.config.read_outputs(
|
||||
&mut self.common.output_configuration_state,
|
||||
&mut self.backend,
|
||||
&mut self.common.shell,
|
||||
&mut *self.common.shell.write().unwrap(),
|
||||
&self.common.event_loop_handle,
|
||||
&mut self.common.workspace_state.update(),
|
||||
&self.common.xdg_activation_state,
|
||||
);
|
||||
self.common.refresh();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -720,7 +729,7 @@ impl State {
|
|||
let backend = self.backend.kms();
|
||||
if let Some(device) = backend.devices.get_mut(&drm_node) {
|
||||
let changes = device.enumerate_surfaces()?;
|
||||
let mut w = self.common.shell.global_space().size.w;
|
||||
let mut w = self.common.shell.read().unwrap().global_space().size.w;
|
||||
for crtc in changes.removed {
|
||||
if let Some(pos) = device
|
||||
.non_desktop_connectors
|
||||
|
|
@ -831,18 +840,23 @@ impl State {
|
|||
self.common
|
||||
.output_configuration_state
|
||||
.add_heads(outputs_added.iter());
|
||||
self.common.config.read_outputs(
|
||||
&mut self.common.output_configuration_state,
|
||||
&mut self.backend,
|
||||
&mut self.common.shell,
|
||||
&self.common.event_loop_handle,
|
||||
);
|
||||
// Don't remove the outputs, before potentially new ones have been initialized.
|
||||
// reading a new config means outputs might become enabled, that were previously disabled.
|
||||
// If we have 0 outputs at some point, we won't quit, but shell doesn't know where to move
|
||||
// windows and workspaces to.
|
||||
for output in outputs_removed {
|
||||
self.common.shell.remove_output(&output);
|
||||
{
|
||||
self.common.config.read_outputs(
|
||||
&mut self.common.output_configuration_state,
|
||||
&mut self.backend,
|
||||
&mut *self.common.shell.write().unwrap(),
|
||||
&self.common.event_loop_handle,
|
||||
&mut self.common.workspace_state.update(),
|
||||
&self.common.xdg_activation_state,
|
||||
);
|
||||
self.common.refresh();
|
||||
// Don't remove the outputs, before potentially new ones have been initialized.
|
||||
// reading a new config means outputs might become enabled, that were previously disabled.
|
||||
// If we have 0 outputs at some point, we won't quit, but shell doesn't know where to move
|
||||
// windows and workspaces to.
|
||||
for output in outputs_removed {
|
||||
self.common.remove_output(&output);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -889,14 +903,17 @@ impl State {
|
|||
|
||||
if self.backend.kms().session.is_active() {
|
||||
for output in outputs_removed {
|
||||
self.common.shell.remove_output(&output);
|
||||
self.common.remove_output(&output);
|
||||
}
|
||||
self.common.config.read_outputs(
|
||||
&mut self.common.output_configuration_state,
|
||||
&mut self.backend,
|
||||
&mut self.common.shell,
|
||||
&mut *self.common.shell.write().unwrap(),
|
||||
&self.common.event_loop_handle,
|
||||
&mut self.common.workspace_state.update(),
|
||||
&self.common.xdg_activation_state,
|
||||
);
|
||||
self.common.refresh();
|
||||
} else {
|
||||
self.common.output_configuration_state.update();
|
||||
}
|
||||
|
|
@ -1178,30 +1195,33 @@ impl Surface {
|
|||
);
|
||||
}
|
||||
|
||||
let (previous_workspace, workspace) = state.shell.workspaces.active(&self.output);
|
||||
let (previous_idx, idx) = state.shell.workspaces.active_num(&self.output);
|
||||
let previous_workspace = previous_workspace
|
||||
.zip(previous_idx)
|
||||
.map(|((w, start), idx)| (w.handle, idx, start));
|
||||
let workspace = (workspace.handle, idx);
|
||||
let mut elements = {
|
||||
let shell = state.shell.read().unwrap();
|
||||
let (previous_workspace, workspace) = shell.workspaces.active(&self.output);
|
||||
let (previous_idx, idx) = shell.workspaces.active_num(&self.output);
|
||||
let previous_workspace = previous_workspace
|
||||
.zip(previous_idx)
|
||||
.map(|((w, start), idx)| (w.handle, idx, start));
|
||||
let workspace = (workspace.handle, idx);
|
||||
|
||||
let mut elements = workspace_elements(
|
||||
Some(&render_node),
|
||||
&mut renderer,
|
||||
&state.shell,
|
||||
&state.config,
|
||||
&state.theme,
|
||||
state.clock.now(),
|
||||
&self.output,
|
||||
previous_workspace,
|
||||
workspace,
|
||||
CursorMode::All,
|
||||
&mut Some(&mut self.fps),
|
||||
false,
|
||||
)
|
||||
.map_err(|err| {
|
||||
anyhow::format_err!("Failed to accumulate elements for rendering: {:?}", err)
|
||||
})?;
|
||||
workspace_elements(
|
||||
Some(&render_node),
|
||||
&mut renderer,
|
||||
&*shell,
|
||||
&state.config,
|
||||
&state.theme,
|
||||
state.clock.now(),
|
||||
&self.output,
|
||||
previous_workspace,
|
||||
workspace,
|
||||
CursorMode::All,
|
||||
&mut Some(&mut self.fps),
|
||||
false,
|
||||
)
|
||||
.map_err(|err| {
|
||||
anyhow::format_err!("Failed to accumulate elements for rendering: {:?}", err)
|
||||
})?
|
||||
};
|
||||
self.fps.elements();
|
||||
|
||||
let frames: Vec<(
|
||||
|
|
@ -1490,6 +1510,8 @@ impl KmsState {
|
|||
shell: &mut Shell,
|
||||
test_only: bool,
|
||||
loop_handle: &LoopHandle<'_, State>,
|
||||
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
|
||||
xdg_activation_state: &XdgActivationState,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let recreated = if let Some(device) = self
|
||||
.devices
|
||||
|
|
@ -1509,7 +1531,12 @@ impl KmsState {
|
|||
|
||||
if !output_config.enabled {
|
||||
if !test_only {
|
||||
shell.remove_output(output);
|
||||
shell.workspaces.remove_output(
|
||||
output,
|
||||
shell.seats.iter(),
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
);
|
||||
if surface.surface.take().is_some() {
|
||||
// just drop it
|
||||
surface.pending = false;
|
||||
|
|
@ -1608,7 +1635,9 @@ impl KmsState {
|
|||
surface.surface = Some(target);
|
||||
true
|
||||
};
|
||||
shell.add_output(output);
|
||||
shell
|
||||
.workspaces
|
||||
.add_output(output, workspace_state, xdg_activation_state);
|
||||
res
|
||||
} else {
|
||||
false
|
||||
|
|
@ -1748,7 +1777,7 @@ impl KmsState {
|
|||
&surface.output,
|
||||
backend.primary_node,
|
||||
target_node,
|
||||
&common.shell,
|
||||
&*common.shell.read().unwrap(),
|
||||
);
|
||||
|
||||
let result = if render_node != target_node {
|
||||
|
|
|
|||
|
|
@ -45,17 +45,26 @@ pub fn init_backend_auto(
|
|||
let output = state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.outputs()
|
||||
.next()
|
||||
.with_context(|| "Backend initialized without output")?;
|
||||
.with_context(|| "Backend initialized without output")
|
||||
.cloned()?;
|
||||
let initial_seat = crate::shell::create_seat(
|
||||
dh,
|
||||
&mut state.common.seat_state,
|
||||
output,
|
||||
&output,
|
||||
&state.common.config,
|
||||
"seat-0".into(),
|
||||
);
|
||||
state.common.shell.seats.add_seat(initial_seat);
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.write()
|
||||
.unwrap()
|
||||
.seats
|
||||
.add_seat(initial_seat);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl WinitState {
|
|||
surface.clone(),
|
||||
&mut self.damage_tracker,
|
||||
age,
|
||||
&state.shell,
|
||||
&*state.shell.read().unwrap(),
|
||||
&state.config,
|
||||
&state.theme,
|
||||
state.clock.now(),
|
||||
|
|
@ -201,7 +201,7 @@ pub fn init_backend(
|
|||
}
|
||||
PumpStatus::Exit(_) => {
|
||||
let output = state.backend.winit().output.clone();
|
||||
state.common.shell.remove_output(&output);
|
||||
state.common.remove_output(&output);
|
||||
if let Some(token) = token.take() {
|
||||
event_loop_handle.remove(token);
|
||||
}
|
||||
|
|
@ -226,13 +226,21 @@ pub fn init_backend(
|
|||
.common
|
||||
.output_configuration_state
|
||||
.add_heads(std::iter::once(&output));
|
||||
state.common.shell.add_output(&output);
|
||||
state.common.config.read_outputs(
|
||||
&mut state.common.output_configuration_state,
|
||||
&mut state.backend,
|
||||
&mut state.common.shell,
|
||||
&state.common.event_loop_handle,
|
||||
);
|
||||
{
|
||||
state.common.add_output(&output);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
state.common.config.read_outputs(
|
||||
&mut state.common.output_configuration_state,
|
||||
&mut state.backend,
|
||||
&mut *shell,
|
||||
&state.common.event_loop_handle,
|
||||
&mut state.common.workspace_state.update(),
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
|
||||
std::mem::drop(shell);
|
||||
state.common.refresh();
|
||||
}
|
||||
state.launch_xwayland(None);
|
||||
|
||||
Ok(())
|
||||
|
|
@ -299,7 +307,7 @@ impl State {
|
|||
// here we can handle special cases for winit inputs
|
||||
match event {
|
||||
WinitEvent::Focus(true) => {
|
||||
for seat in self.common.shell.seats.iter() {
|
||||
for seat in self.common.shell.read().unwrap().seats.iter() {
|
||||
let devices = seat.user_data().get::<Devices>().unwrap();
|
||||
if devices.has_device(&WinitVirtualDevice) {
|
||||
seat.set_active_output(&self.backend.winit().output);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ impl Surface {
|
|||
buffer.clone(),
|
||||
&mut self.damage_tracker,
|
||||
age as usize,
|
||||
&state.shell,
|
||||
&*state.shell.read().unwrap(),
|
||||
&state.config,
|
||||
&state.theme,
|
||||
state.clock.now(),
|
||||
|
|
@ -364,13 +364,21 @@ pub fn init_backend(
|
|||
.common
|
||||
.output_configuration_state
|
||||
.add_heads(std::iter::once(&output));
|
||||
state.common.shell.add_output(&output);
|
||||
state.common.config.read_outputs(
|
||||
&mut state.common.output_configuration_state,
|
||||
&mut state.backend,
|
||||
&mut state.common.shell,
|
||||
&state.common.event_loop_handle,
|
||||
);
|
||||
{
|
||||
state.common.add_output(&output);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
state.common.config.read_outputs(
|
||||
&mut state.common.output_configuration_state,
|
||||
&mut state.backend,
|
||||
&mut *shell,
|
||||
&state.common.event_loop_handle,
|
||||
&mut state.common.workspace_state.update(),
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
|
||||
std::mem::drop(shell);
|
||||
state.common.refresh();
|
||||
}
|
||||
state.launch_xwayland(None);
|
||||
|
||||
event_loop
|
||||
|
|
@ -395,7 +403,7 @@ pub fn init_backend(
|
|||
.surfaces
|
||||
.retain(|s| s.window.id() != window_id);
|
||||
for output in outputs_removed.into_iter() {
|
||||
state.common.shell.remove_output(&output);
|
||||
state.common.remove_output(&output);
|
||||
}
|
||||
}
|
||||
X11Event::Resized {
|
||||
|
|
@ -504,7 +512,7 @@ impl State {
|
|||
.unwrap();
|
||||
|
||||
let device = event.device();
|
||||
for seat in self.common.shell.seats.iter() {
|
||||
for seat in self.common.shell.read().unwrap().seats.iter() {
|
||||
let devices = seat.user_data().get::<Devices>().unwrap();
|
||||
if devices.has_device(&device) {
|
||||
seat.set_active_output(&output);
|
||||
|
|
@ -518,7 +526,7 @@ impl State {
|
|||
|
||||
self.process_input_event(event, false);
|
||||
// TODO actually figure out the output
|
||||
for output in self.common.shell.outputs() {
|
||||
for output in self.common.shell.read().unwrap().outputs() {
|
||||
self.backend.x11().schedule_render(output);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@
|
|||
use crate::{
|
||||
shell::Shell,
|
||||
state::{BackendData, State},
|
||||
wayland::protocols::output_configuration::OutputConfigurationState,
|
||||
wayland::protocols::{
|
||||
output_configuration::OutputConfigurationState, workspace::WorkspaceUpdateGuard,
|
||||
},
|
||||
};
|
||||
use cosmic_config::{ConfigGet, CosmicConfigEntry};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smithay::wayland::xdg_activation::XdgActivationState;
|
||||
pub use smithay::{
|
||||
backend::input::KeyState,
|
||||
input::keyboard::{keysyms as KeySyms, Keysym, ModifiersState},
|
||||
|
|
@ -277,6 +280,8 @@ impl Config {
|
|||
backend: &mut BackendData,
|
||||
shell: &mut Shell,
|
||||
loop_handle: &LoopHandle<'_, State>,
|
||||
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
|
||||
xdg_activation_state: &XdgActivationState,
|
||||
) {
|
||||
let outputs = output_state.outputs().collect::<Vec<_>>();
|
||||
let mut infos = outputs
|
||||
|
|
@ -308,9 +313,14 @@ impl Config {
|
|||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow_mut() = output_config;
|
||||
if let Err(err) =
|
||||
backend.apply_config_for_output(&output, false, shell, loop_handle)
|
||||
{
|
||||
if let Err(err) = backend.apply_config_for_output(
|
||||
&output,
|
||||
false,
|
||||
shell,
|
||||
loop_handle,
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
) {
|
||||
warn!(
|
||||
?err,
|
||||
"Failed to set new config for output {}.",
|
||||
|
|
@ -339,9 +349,14 @@ impl Config {
|
|||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow_mut() = output_config;
|
||||
if let Err(err) =
|
||||
backend.apply_config_for_output(&output, false, shell, loop_handle)
|
||||
{
|
||||
if let Err(err) = backend.apply_config_for_output(
|
||||
&output,
|
||||
false,
|
||||
shell,
|
||||
loop_handle,
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
) {
|
||||
error!(?err, "Failed to reset config for output {}.", output.name());
|
||||
} else {
|
||||
if enabled {
|
||||
|
|
@ -357,9 +372,14 @@ impl Config {
|
|||
self.write_outputs(output_state.outputs());
|
||||
} else {
|
||||
for output in outputs {
|
||||
if let Err(err) =
|
||||
backend.apply_config_for_output(&output, false, shell, loop_handle)
|
||||
{
|
||||
if let Err(err) = backend.apply_config_for_output(
|
||||
&output,
|
||||
false,
|
||||
shell,
|
||||
loop_handle,
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
) {
|
||||
warn!(
|
||||
?err,
|
||||
"Failed to set new config for output {}.",
|
||||
|
|
@ -518,7 +538,15 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
|
|||
match key.as_str() {
|
||||
"xkb_config" => {
|
||||
let value = get_config::<XkbConfig>(&config, "xkb_config");
|
||||
let seats = state.common.shell.seats.iter().cloned().collect::<Vec<_>>();
|
||||
let seats = state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
for seat in seats.into_iter() {
|
||||
if let Some(keyboard) = seat.get_keyboard() {
|
||||
if let Err(err) = keyboard.set_xkb_config(state, xkb_config_to_wl(&value)) {
|
||||
|
|
@ -547,27 +575,41 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
|
|||
"workspaces" => {
|
||||
state.common.config.cosmic_conf.workspaces =
|
||||
get_config::<WorkspaceConfig>(&config, "workspaces");
|
||||
state.common.shell.update_config(&state.common.config);
|
||||
state.common.update_config();
|
||||
}
|
||||
"autotile" => {
|
||||
let new = get_config::<bool>(&config, "autotile");
|
||||
if new != state.common.config.cosmic_conf.autotile {
|
||||
state.common.config.cosmic_conf.autotile = new;
|
||||
state.common.shell.update_autotile(new);
|
||||
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let shell_ref = &mut *shell;
|
||||
shell_ref.workspaces.update_autotile(
|
||||
new,
|
||||
&mut state.common.workspace_state.update(),
|
||||
shell_ref.seats.iter(),
|
||||
);
|
||||
}
|
||||
}
|
||||
"autotile_behavior" => {
|
||||
let new = get_config::<TileBehavior>(&config, "autotile_behavior");
|
||||
if new != state.common.config.cosmic_conf.autotile_behavior {
|
||||
state.common.config.cosmic_conf.autotile_behavior = new;
|
||||
state.common.shell.update_autotile_behavior(new);
|
||||
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let shell_ref = &mut *shell;
|
||||
shell_ref.workspaces.update_autotile_behavior(
|
||||
new,
|
||||
&mut state.common.workspace_state.update(),
|
||||
shell_ref.seats.iter(),
|
||||
);
|
||||
}
|
||||
}
|
||||
"active_hint" => {
|
||||
let new = get_config::<bool>(&config, "active_hint");
|
||||
if new != state.common.config.cosmic_conf.active_hint {
|
||||
state.common.config.cosmic_conf.active_hint = new;
|
||||
state.common.shell.update_config(&state.common.config);
|
||||
state.common.update_config();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
954
src/input/mod.rs
954
src/input/mod.rs
File diff suppressed because it is too large
Load diff
44
src/main.rs
44
src/main.rs
|
|
@ -92,7 +92,16 @@ fn main() -> Result<()> {
|
|||
// run the event loop
|
||||
event_loop.run(None, &mut state, |state| {
|
||||
// shall we shut down?
|
||||
if state.common.shell.outputs().next().is_none() || state.common.should_stop {
|
||||
if state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.outputs()
|
||||
.next()
|
||||
.is_none()
|
||||
|| state.common.should_stop
|
||||
{
|
||||
info!("Shutting down");
|
||||
state.common.event_loop_signal.stop();
|
||||
state.common.event_loop_signal.wakeup();
|
||||
|
|
@ -100,29 +109,25 @@ fn main() -> Result<()> {
|
|||
}
|
||||
|
||||
// trigger routines
|
||||
let clients = state.common.shell.update_animations();
|
||||
let clients = state.common.shell.write().unwrap().update_animations();
|
||||
{
|
||||
let dh = state.common.display_handle.clone();
|
||||
for client in clients.values() {
|
||||
client_compositor_state(&client).blocker_cleared(state, &dh);
|
||||
}
|
||||
}
|
||||
state.common.shell.refresh();
|
||||
state.common.refresh();
|
||||
state::Common::refresh_focus(state);
|
||||
state.common.update_x11_stacking_order();
|
||||
|
||||
if state.common.shell.animations_going() {
|
||||
for output in state
|
||||
.common
|
||||
.shell
|
||||
.outputs()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
{
|
||||
state
|
||||
.backend
|
||||
.schedule_render(&state.common.event_loop_handle, &output);
|
||||
{
|
||||
let shell = state.common.shell.read().unwrap();
|
||||
if shell.animations_going() {
|
||||
for output in shell.outputs().cloned().collect::<Vec<_>>().into_iter() {
|
||||
state
|
||||
.backend
|
||||
.schedule_render(&state.common.event_loop_handle, &output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +186,14 @@ fn init_wayland_display(
|
|||
let node = match &state.backend {
|
||||
BackendData::Kms(kms_state) if kms_state.auto_assign => kms_state
|
||||
.target_node_for_output(
|
||||
&state.common.shell.seats.last_active().active_output(),
|
||||
&state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.active_output(),
|
||||
),
|
||||
_ => None,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -70,13 +70,7 @@ pub fn get_env(state: &State) -> Result<HashMap<String, String>> {
|
|||
.into_string()
|
||||
.map_err(|_| anyhow!("wayland socket is no valid utf-8 string?"))?,
|
||||
);
|
||||
if let Some(display) = state
|
||||
.common
|
||||
.shell
|
||||
.xwayland_state
|
||||
.as_ref()
|
||||
.map(|s| s.display)
|
||||
{
|
||||
if let Some(display) = state.common.xwayland_state.as_ref().map(|s| s.display) {
|
||||
env.insert(String::from("DISPLAY"), format!(":{}", display));
|
||||
}
|
||||
Ok(env)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
focus::{target::PointerFocusTarget, FocusDirection},
|
||||
grabs::{ReleaseMode, ResizeEdge},
|
||||
layout::tiling::NodeDesc,
|
||||
Direction, Shell,
|
||||
Direction,
|
||||
},
|
||||
state::State,
|
||||
utils::{
|
||||
|
|
@ -664,14 +664,25 @@ impl Program for CosmicStackInternal {
|
|||
let active = self.active.load(Ordering::SeqCst);
|
||||
if let Some(surface) = self.windows.lock().unwrap()[active].wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
Shell::move_request(
|
||||
state,
|
||||
let res = state.common.shell.write().unwrap().move_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
ReleaseMode::NoMouseButtons,
|
||||
false,
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -683,7 +694,13 @@ impl Program for CosmicStackInternal {
|
|||
*self.potential_drag.lock().unwrap() = None;
|
||||
if let Some(surface) = self.windows.lock().unwrap().get(idx).cloned() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
if let Some(mapped) = state.common.shell.element_for_surface(&surface) {
|
||||
if let Some(mapped) = state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.element_for_surface(&surface)
|
||||
{
|
||||
mapped.stack_ref().unwrap().set_active(&surface);
|
||||
}
|
||||
});
|
||||
|
|
@ -703,11 +720,10 @@ impl Program for CosmicStackInternal {
|
|||
let active = self.active.load(Ordering::SeqCst);
|
||||
if let Some(surface) = self.windows.lock().unwrap()[active].wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
if let Some(mapped) =
|
||||
state.common.shell.element_for_surface(&surface).cloned()
|
||||
{
|
||||
let shell = state.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&surface).cloned() {
|
||||
let position = if let Some((output, set)) =
|
||||
state.common.shell.workspaces.sets.iter().find(|(_, set)| {
|
||||
shell.workspaces.sets.iter().find(|(_, set)| {
|
||||
set.sticky_layer.mapped().any(|m| m == &mapped)
|
||||
}) {
|
||||
set.sticky_layer
|
||||
|
|
@ -715,9 +731,7 @@ impl Program for CosmicStackInternal {
|
|||
.unwrap()
|
||||
.loc
|
||||
.to_global(output)
|
||||
} else if let Some(workspace) =
|
||||
state.common.shell.space_for_mut(&mapped)
|
||||
{
|
||||
} else if let Some(workspace) = shell.space_for(&mapped) {
|
||||
let Some(elem_geo) = workspace.element_geometry(&mapped) else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -732,14 +746,22 @@ impl Program for CosmicStackInternal {
|
|||
.current_location()
|
||||
.to_i32_round();
|
||||
cursor.y -= TAB_HEIGHT;
|
||||
Shell::menu_request(
|
||||
state,
|
||||
let res = shell.menu_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
cursor - position.as_logical(),
|
||||
true,
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some((grab, focus)) = res {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -749,28 +771,36 @@ impl Program for CosmicStackInternal {
|
|||
if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() {
|
||||
if let Some(surface) = self.windows.lock().unwrap()[idx].wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
if let Some(mapped) =
|
||||
state.common.shell.element_for_surface(&surface).cloned()
|
||||
{
|
||||
if let Some(workspace) = state.common.shell.space_for_mut(&mapped) {
|
||||
let shell = state.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&surface).cloned() {
|
||||
if let Some(workspace) = shell.space_for(&mapped) {
|
||||
let Some(elem_geo) = workspace.element_geometry(&mapped) else {
|
||||
return;
|
||||
};
|
||||
let position = elem_geo.loc.to_global(&workspace.output);
|
||||
|
||||
let mut cursor = seat
|
||||
.get_pointer()
|
||||
.unwrap()
|
||||
.current_location()
|
||||
.to_i32_round();
|
||||
cursor.y -= TAB_HEIGHT;
|
||||
Shell::menu_request(
|
||||
state,
|
||||
let res = shell.menu_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
cursor - position.as_logical(),
|
||||
false,
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some((grab, focus)) = res {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1175,18 +1205,30 @@ impl PointerTarget<State> for CosmicStack {
|
|||
.with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned())
|
||||
{
|
||||
let seat = seat.clone();
|
||||
let serial = event.serial;
|
||||
surface.try_force_undecorated(false);
|
||||
surface.send_configure();
|
||||
if let Some(surface) = surface.wl_surface() {
|
||||
let _ = data.common.event_loop_handle.insert_idle(move |state| {
|
||||
Shell::move_request(
|
||||
state,
|
||||
let res = state.common.shell.write().unwrap().move_request(
|
||||
&surface,
|
||||
&seat,
|
||||
None,
|
||||
serial,
|
||||
ReleaseMode::NoMouseButtons,
|
||||
true,
|
||||
)
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1220,8 +1262,7 @@ impl PointerTarget<State> for CosmicStack {
|
|||
return;
|
||||
};
|
||||
self.0.loop_handle().insert_idle(move |state| {
|
||||
Shell::resize_request(
|
||||
state,
|
||||
let res = state.common.shell.write().unwrap().resize_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
|
|
@ -1236,7 +1277,16 @@ impl PointerTarget<State> for CosmicStack {
|
|||
Focus::ResizeRight => ResizeEdge::RIGHT,
|
||||
Focus::Header => unreachable!(),
|
||||
},
|
||||
)
|
||||
);
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
None => {}
|
||||
|
|
@ -1279,14 +1329,25 @@ impl PointerTarget<State> for CosmicStack {
|
|||
surface.send_configure();
|
||||
if let Some(surface) = surface.wl_surface() {
|
||||
let _ = data.common.event_loop_handle.insert_idle(move |state| {
|
||||
Shell::move_request(
|
||||
state,
|
||||
let res = state.common.shell.write().unwrap().move_request(
|
||||
&surface,
|
||||
&seat,
|
||||
None,
|
||||
serial,
|
||||
ReleaseMode::NoMouseButtons,
|
||||
true,
|
||||
)
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use crate::{
|
|||
shell::{
|
||||
focus::target::PointerFocusTarget,
|
||||
grabs::{ReleaseMode, ResizeEdge},
|
||||
Shell,
|
||||
},
|
||||
state::State,
|
||||
utils::{
|
||||
|
|
@ -387,14 +386,25 @@ impl Program for CosmicWindowInternal {
|
|||
if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() {
|
||||
if let Some(surface) = self.window.wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
Shell::move_request(
|
||||
state,
|
||||
let res = state.common.shell.write().unwrap().move_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
ReleaseMode::NoMouseButtons,
|
||||
false,
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -402,10 +412,9 @@ impl Program for CosmicWindowInternal {
|
|||
Message::Minimize => {
|
||||
if let Some(surface) = self.window.wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
if let Some(mapped) =
|
||||
state.common.shell.element_for_surface(&surface).cloned()
|
||||
{
|
||||
state.common.shell.minimize_request(&mapped)
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&surface).cloned() {
|
||||
shell.minimize_request(&mapped)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -413,11 +422,10 @@ impl Program for CosmicWindowInternal {
|
|||
Message::Maximize => {
|
||||
if let Some(surface) = self.window.wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
if let Some(mapped) =
|
||||
state.common.shell.element_for_surface(&surface).cloned()
|
||||
{
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
state.common.shell.maximize_toggle(&mapped, &seat)
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&surface).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_toggle(&mapped, &seat)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -427,11 +435,10 @@ impl Program for CosmicWindowInternal {
|
|||
if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() {
|
||||
if let Some(surface) = self.window.wl_surface() {
|
||||
loop_handle.insert_idle(move |state| {
|
||||
if let Some(mapped) =
|
||||
state.common.shell.element_for_surface(&surface).cloned()
|
||||
{
|
||||
let shell = state.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&surface).cloned() {
|
||||
let position = if let Some((output, set)) =
|
||||
state.common.shell.workspaces.sets.iter().find(|(_, set)| {
|
||||
shell.workspaces.sets.iter().find(|(_, set)| {
|
||||
set.sticky_layer.mapped().any(|m| m == &mapped)
|
||||
}) {
|
||||
set.sticky_layer
|
||||
|
|
@ -439,9 +446,7 @@ impl Program for CosmicWindowInternal {
|
|||
.unwrap()
|
||||
.loc
|
||||
.to_global(output)
|
||||
} else if let Some(workspace) =
|
||||
state.common.shell.space_for_mut(&mapped)
|
||||
{
|
||||
} else if let Some(workspace) = shell.space_for(&mapped) {
|
||||
let Some(elem_geo) = workspace.element_geometry(&mapped) else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -450,20 +455,24 @@ impl Program for CosmicWindowInternal {
|
|||
return;
|
||||
};
|
||||
|
||||
let mut cursor = seat
|
||||
.get_pointer()
|
||||
.unwrap()
|
||||
.current_location()
|
||||
.to_i32_round();
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
let mut cursor = pointer.current_location().to_i32_round();
|
||||
cursor.y -= SSD_HEIGHT;
|
||||
Shell::menu_request(
|
||||
state,
|
||||
|
||||
let res = shell.menu_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
cursor - position.as_logical(),
|
||||
false,
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some((grab, focus)) = res {
|
||||
pointer.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -734,8 +743,7 @@ impl PointerTarget<State> for CosmicWindow {
|
|||
return;
|
||||
};
|
||||
self.0.loop_handle().insert_idle(move |state| {
|
||||
Shell::resize_request(
|
||||
state,
|
||||
let res = state.common.shell.write().unwrap().resize_request(
|
||||
&surface,
|
||||
&seat,
|
||||
serial,
|
||||
|
|
@ -750,7 +758,17 @@ impl PointerTarget<State> for CosmicWindow {
|
|||
Focus::ResizeRight => ResizeEdge::RIGHT,
|
||||
Focus::Header => unreachable!(),
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
None => {}
|
||||
|
|
|
|||
|
|
@ -107,9 +107,13 @@ impl Shell {
|
|||
) {
|
||||
let element = match target {
|
||||
Some(KeyboardFocusTarget::Element(mapped)) => Some(mapped.clone()),
|
||||
Some(KeyboardFocusTarget::Fullscreen(window)) => {
|
||||
state.common.shell.element_for_surface(window).cloned()
|
||||
}
|
||||
Some(KeyboardFocusTarget::Fullscreen(window)) => state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.element_for_surface(window)
|
||||
.cloned(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
|
@ -117,7 +121,12 @@ impl Shell {
|
|||
if mapped.is_minimized() {
|
||||
return;
|
||||
}
|
||||
state.common.shell.append_focus_stack(&mapped, seat);
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.write()
|
||||
.unwrap()
|
||||
.append_focus_stack(&mapped, seat);
|
||||
}
|
||||
|
||||
// update keyboard focus
|
||||
|
|
@ -130,7 +139,7 @@ impl Shell {
|
|||
);
|
||||
}
|
||||
|
||||
state.common.shell.update_active();
|
||||
state.common.shell.write().unwrap().update_active();
|
||||
}
|
||||
|
||||
pub fn append_focus_stack(&mut self, mapped: &CosmicMapped, seat: &Seat<State>) {
|
||||
|
|
@ -233,25 +242,27 @@ fn raise_with_children(floating_layer: &mut FloatingLayout, focused: &CosmicMapp
|
|||
|
||||
impl Common {
|
||||
pub fn refresh_focus(state: &mut State) {
|
||||
for seat in state
|
||||
let seats = state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
{
|
||||
.collect::<Vec<_>>();
|
||||
for seat in seats.into_iter() {
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let output = seat.active_output();
|
||||
if !state.common.shell.outputs().any(|o| o == &output) {
|
||||
seat.set_active_output(&state.common.shell.outputs().next().unwrap());
|
||||
if !shell.outputs().any(|o| o == &output) {
|
||||
seat.set_active_output(&shell.outputs().next().unwrap());
|
||||
continue;
|
||||
}
|
||||
let last_known_focus = ActiveFocus::get(&seat);
|
||||
|
||||
if let Some(target) = last_known_focus {
|
||||
if target.alive() {
|
||||
if focus_target_is_valid(&mut state.common.shell, &seat, &output, target) {
|
||||
if focus_target_is_valid(&mut *shell, &seat, &output, target) {
|
||||
continue; // Focus is valid
|
||||
} else {
|
||||
trace!("Wrong Window, focus fixup");
|
||||
|
|
@ -266,6 +277,8 @@ impl Common {
|
|||
if !popup_grab.has_ended() {
|
||||
if let Some(new) = popup_grab.current_grab() {
|
||||
trace!("restore focus to previous popup grab");
|
||||
std::mem::drop(shell);
|
||||
|
||||
if let Some(keyboard) = seat.get_keyboard() {
|
||||
keyboard.set_focus(
|
||||
state,
|
||||
|
|
@ -285,7 +298,7 @@ impl Common {
|
|||
trace!("Surface dead, focus fixup");
|
||||
}
|
||||
} else {
|
||||
let workspace = state.common.shell.active_space(&output);
|
||||
let workspace = shell.active_space(&output);
|
||||
let focus_stack = workspace.focus_stack.get(&seat);
|
||||
|
||||
if focus_stack.last().is_none() {
|
||||
|
|
@ -309,7 +322,9 @@ impl Common {
|
|||
}
|
||||
|
||||
// update keyboard focus
|
||||
let target = update_focus_target(&state.common.shell, &seat, &output);
|
||||
let target = update_focus_target(&*shell, &seat, &output);
|
||||
std::mem::drop(shell);
|
||||
|
||||
if let Some(keyboard) = seat.get_keyboard() {
|
||||
debug!("Restoring focus to {:?}", target.as_ref());
|
||||
keyboard.set_focus(state, target.clone(), SERIAL_COUNTER.next_serial());
|
||||
|
|
@ -318,7 +333,7 @@ impl Common {
|
|||
}
|
||||
}
|
||||
|
||||
state.common.shell.update_active()
|
||||
state.common.shell.write().unwrap().update_active()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ impl PointerFocusTarget {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toplevel(&self, data: &mut State) -> Option<CosmicSurface> {
|
||||
pub fn toplevel(&self, shell: &Shell) -> Option<CosmicSurface> {
|
||||
match &self {
|
||||
PointerFocusTarget::WlSurface {
|
||||
toplevel: Some(PointerFocusToplevel::Surface(surface)),
|
||||
|
|
@ -142,12 +142,7 @@ impl PointerFocusTarget {
|
|||
toplevel: Some(PointerFocusToplevel::Popup(PopupKind::Xdg(popup))),
|
||||
..
|
||||
} => get_popup_toplevel(popup)
|
||||
.and_then(|s| {
|
||||
data.common
|
||||
.shell
|
||||
.element_for_surface(&s)
|
||||
.map(|mapped| (mapped, s))
|
||||
})
|
||||
.and_then(|s| shell.element_for_surface(&s).map(|mapped| (mapped, s)))
|
||||
.and_then(|(m, s)| {
|
||||
m.windows()
|
||||
.find(|(w, _)| w.wl_surface().map(|s2| s == s2).unwrap_or(false))
|
||||
|
|
@ -210,7 +205,8 @@ impl IsAlive for KeyboardFocusTarget {
|
|||
|
||||
impl PointerTarget<State> for PointerFocusTarget {
|
||||
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
|
||||
if let Some(element) = self.toplevel(data) {
|
||||
let toplevel = self.toplevel(&*data.common.shell.read().unwrap());
|
||||
if let Some(element) = toplevel {
|
||||
for session in element.cursor_sessions() {
|
||||
session.set_cursor_pos(Some(
|
||||
event
|
||||
|
|
@ -238,7 +234,8 @@ impl PointerTarget<State> for PointerFocusTarget {
|
|||
}
|
||||
}
|
||||
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
|
||||
if let Some(element) = self.toplevel(data) {
|
||||
let toplevel = self.toplevel(&*data.common.shell.read().unwrap());
|
||||
if let Some(element) = toplevel {
|
||||
for session in element.cursor_sessions() {
|
||||
session.set_cursor_pos(Some(
|
||||
event
|
||||
|
|
@ -308,7 +305,8 @@ impl PointerTarget<State> for PointerFocusTarget {
|
|||
}
|
||||
}
|
||||
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
||||
if let Some(element) = self.toplevel(data) {
|
||||
let toplevel = self.toplevel(&*data.common.shell.read().unwrap());
|
||||
if let Some(element) = toplevel {
|
||||
for session in element.cursor_sessions() {
|
||||
session.set_cursor_pos(None);
|
||||
session.set_cursor_hotspot((0, 0));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use smithay::wayland::seat::WaylandFocus;
|
||||
use smithay::{input::pointer::MotionEvent, utils::SERIAL_COUNTER, wayland::seat::WaylandFocus};
|
||||
|
||||
use crate::{
|
||||
config::{Action, StaticConfig},
|
||||
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
shell::{
|
||||
element::{CosmicMapped, CosmicWindow},
|
||||
grabs::ReleaseMode,
|
||||
CosmicSurface, Shell,
|
||||
CosmicSurface, PointGlobalExt, Shell,
|
||||
},
|
||||
state::State,
|
||||
utils::{prelude::SeatExt, screenshot::screenshot_window},
|
||||
|
|
@ -15,61 +15,57 @@ use crate::{
|
|||
use super::{Item, ResizeEdge};
|
||||
|
||||
fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
if let Some(new_focus) = state.common.shell.toggle_stacking(mapped) {
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(new_focus) = shell.toggle_stacking(mapped) {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(state, Some(&new_focus), &seat, None);
|
||||
}
|
||||
}
|
||||
|
||||
fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let (current_handle, output) = {
|
||||
let Some(ws) = state.common.shell.space_for(mapped) else {
|
||||
let Some(ws) = shell.space_for(mapped) else {
|
||||
return;
|
||||
};
|
||||
(ws.handle, ws.output.clone())
|
||||
};
|
||||
let maybe_handle = state
|
||||
.common
|
||||
.shell
|
||||
let maybe_handle = shell
|
||||
.workspaces
|
||||
.spaces_for_output(&output)
|
||||
.enumerate()
|
||||
.find_map(|(i, space)| (space.handle == current_handle).then_some(i))
|
||||
.and_then(|i| i.checked_sub(1))
|
||||
.and_then(|i| {
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.workspaces
|
||||
.get(i, &output)
|
||||
.map(|s| s.handle)
|
||||
});
|
||||
.and_then(|i| shell.workspaces.get(i, &output).map(|s| s.handle));
|
||||
if let Some(prev_handle) = maybe_handle {
|
||||
if let Some((target, _)) = state.common.shell.move_window(
|
||||
let res = shell.move_window(
|
||||
Some(&seat),
|
||||
mapped,
|
||||
¤t_handle,
|
||||
&prev_handle,
|
||||
true,
|
||||
None,
|
||||
) {
|
||||
&mut state.common.workspace_state.update(),
|
||||
);
|
||||
if let Some((target, _)) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(state, Some(&target), &seat, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let (current_handle, output) = {
|
||||
let Some(ws) = state.common.shell.space_for(mapped) else {
|
||||
let Some(ws) = shell.space_for(mapped) else {
|
||||
return;
|
||||
};
|
||||
(ws.handle, ws.output.clone())
|
||||
};
|
||||
let maybe_handle = state
|
||||
.common
|
||||
.shell
|
||||
let maybe_handle = shell
|
||||
.workspaces
|
||||
.spaces_for_output(&output)
|
||||
.skip_while(|space| space.handle != current_handle)
|
||||
|
|
@ -77,14 +73,17 @@ fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
|
|||
.next()
|
||||
.map(|space| space.handle);
|
||||
if let Some(next_handle) = maybe_handle {
|
||||
if let Some((target, _point)) = state.common.shell.move_window(
|
||||
let res = shell.move_window(
|
||||
Some(&seat),
|
||||
mapped,
|
||||
¤t_handle,
|
||||
&next_handle,
|
||||
true,
|
||||
None,
|
||||
) {
|
||||
&mut state.common.workspace_state.update(),
|
||||
);
|
||||
if let Some((target, _point)) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(state, Some(&target), &seat, None)
|
||||
}
|
||||
}
|
||||
|
|
@ -114,9 +113,10 @@ pub fn tab_items(
|
|||
)
|
||||
.into();
|
||||
|
||||
let seat = state.common.shell.seats.last_active();
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let output = seat.active_output();
|
||||
let workspace = state.common.shell.workspaces.active_mut(&output);
|
||||
let workspace = shell.workspaces.active_mut(&output);
|
||||
if is_tiled {
|
||||
for mapped in workspace
|
||||
.mapped()
|
||||
|
|
@ -127,7 +127,7 @@ pub fn tab_items(
|
|||
{
|
||||
workspace.unmaximize_request(&mapped);
|
||||
}
|
||||
let focus_stack = workspace.focus_stack.get(seat);
|
||||
let focus_stack = workspace.focus_stack.get(&seat);
|
||||
workspace
|
||||
.tiling_layer
|
||||
.map(mapped, Some(focus_stack.iter()), None);
|
||||
|
|
@ -197,7 +197,12 @@ pub fn window_items(
|
|||
Item::new(fl!("window-menu-minimize"), move |handle| {
|
||||
let mapped = minimize_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
state.common.shell.minimize_request(&mapped);
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.write()
|
||||
.unwrap()
|
||||
.minimize_request(&mapped);
|
||||
});
|
||||
})
|
||||
.shortcut(config.get_shortcut_for_action(&Action::Minimize)),
|
||||
|
|
@ -206,8 +211,9 @@ pub fn window_items(
|
|||
Item::new(fl!("window-menu-maximize"), move |handle| {
|
||||
let mapped = maximize_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
state.common.shell.maximize_toggle(&mapped, &seat);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_toggle(&mapped, &seat);
|
||||
});
|
||||
})
|
||||
.shortcut(config.get_shortcut_for_action(&Action::Maximize))
|
||||
|
|
@ -217,8 +223,9 @@ pub fn window_items(
|
|||
Item::new(fl!("window-menu-tiled"), move |handle| {
|
||||
let tile_clone = tile_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
if let Some(ws) = state.common.shell.space_for_mut(&tile_clone) {
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(ws) = shell.space_for_mut(&tile_clone) {
|
||||
ws.toggle_floating_window(&seat, &tile_clone);
|
||||
}
|
||||
});
|
||||
|
|
@ -238,8 +245,36 @@ pub fn window_items(
|
|||
let move_clone = move_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
if let Some(surface) = move_clone.wl_surface() {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
Shell::move_request(state, &surface, &seat, None, ReleaseMode::Click, false);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res = shell.move_request(
|
||||
&surface,
|
||||
&seat,
|
||||
None,
|
||||
ReleaseMode::Click,
|
||||
false,
|
||||
&state.common.config,
|
||||
&state.common.event_loop_handle,
|
||||
&state.common.xdg_activation_state,
|
||||
);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some((grab, focus)) = res {
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(
|
||||
state,
|
||||
grab,
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
)
|
||||
} else {
|
||||
seat.get_pointer().unwrap().set_grab(
|
||||
state,
|
||||
grab,
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
focus,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})),
|
||||
|
|
@ -249,32 +284,122 @@ pub fn window_items(
|
|||
Item::new(fl!("window-menu-resize-edge-top"), move |handle| {
|
||||
let resize_clone = resize_top_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::TOP);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res = shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::TOP);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some(((target, loc), (grab, focus))) = res {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
pointer.motion(
|
||||
state,
|
||||
target,
|
||||
&MotionEvent {
|
||||
location: loc.as_logical().to_f64(),
|
||||
serial,
|
||||
time: 0,
|
||||
},
|
||||
);
|
||||
pointer.frame(state);
|
||||
pointer.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.disabled(!possible_resizes.contains(ResizeEdge::TOP)),
|
||||
Item::new(fl!("window-menu-resize-edge-left"), move |handle| {
|
||||
let resize_clone = resize_left_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::LEFT);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res = shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::LEFT);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some(((target, loc), (grab, focus))) = res {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
pointer.motion(
|
||||
state,
|
||||
target,
|
||||
&MotionEvent {
|
||||
location: loc.as_logical().to_f64(),
|
||||
serial,
|
||||
time: 0,
|
||||
},
|
||||
);
|
||||
pointer.frame(state);
|
||||
pointer.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.disabled(!possible_resizes.contains(ResizeEdge::LEFT)),
|
||||
Item::new(fl!("window-menu-resize-edge-right"), move |handle| {
|
||||
let resize_clone = resize_right_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::RIGHT);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res =
|
||||
shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::RIGHT);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some(((target, loc), (grab, focus))) = res {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
pointer.motion(
|
||||
state,
|
||||
target,
|
||||
&MotionEvent {
|
||||
location: loc.as_logical().to_f64(),
|
||||
serial,
|
||||
time: 0,
|
||||
},
|
||||
);
|
||||
pointer.frame(state);
|
||||
pointer.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.disabled(!possible_resizes.contains(ResizeEdge::RIGHT)),
|
||||
Item::new(fl!("window-menu-resize-edge-bottom"), move |handle| {
|
||||
let resize_clone = resize_bottom_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::BOTTOM);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res =
|
||||
shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::BOTTOM);
|
||||
|
||||
std::mem::drop(shell);
|
||||
if let Some(((target, loc), (grab, focus))) = res {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(state, grab, serial);
|
||||
} else {
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
pointer.motion(
|
||||
state,
|
||||
target,
|
||||
&MotionEvent {
|
||||
location: loc.as_logical().to_f64(),
|
||||
serial,
|
||||
time: 0,
|
||||
},
|
||||
);
|
||||
pointer.frame(state);
|
||||
pointer.set_grab(state, grab, serial, focus);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.disabled(!possible_resizes.contains(ResizeEdge::BOTTOM)),
|
||||
|
|
@ -301,8 +426,9 @@ pub fn window_items(
|
|||
Item::new(fl!("window-menu-sticky"), move |handle| {
|
||||
let mapped = sticky_clone.clone();
|
||||
let _ = handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active().clone();
|
||||
state.common.shell.toggle_sticky(&seat, &mapped);
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.toggle_sticky(&seat, &mapped);
|
||||
});
|
||||
})
|
||||
.toggled(is_sticky),
|
||||
|
|
|
|||
|
|
@ -216,7 +216,14 @@ impl Program for ContextMenu {
|
|||
if let Some(Item::Submenu { items, .. }) = self.items.get_mut(idx) {
|
||||
let items = items.clone();
|
||||
let _ = loop_handle.insert_idle(move |state| {
|
||||
let seat = state.common.shell.seats.last_active();
|
||||
let seat = state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.clone();
|
||||
let grab_state = seat
|
||||
.user_data()
|
||||
.get::<SeatMenuGrabState>()
|
||||
|
|
@ -301,7 +308,14 @@ impl Program for ContextMenu {
|
|||
Message::ItemLeft(idx, _) => {
|
||||
if let Some(Item::Submenu { .. }) = self.items.get_mut(idx) {
|
||||
let _ = loop_handle.insert_idle(|state| {
|
||||
let seat = state.common.shell.seats.last_active();
|
||||
let seat = state
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.clone();
|
||||
let grab_state = seat
|
||||
.user_data()
|
||||
.get::<SeatMenuGrabState>()
|
||||
|
|
|
|||
|
|
@ -153,6 +153,15 @@ impl From<ResizeForkGrab> for ResizeGrab {
|
|||
}
|
||||
}
|
||||
|
||||
impl ResizeGrab {
|
||||
pub fn is_touch_grab(&self) -> bool {
|
||||
match self {
|
||||
ResizeGrab::Floating(grab) => grab.is_touch_grab(),
|
||||
ResizeGrab::Tiling(grab) => grab.is_touch_grab(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerGrab<State> for ResizeGrab {
|
||||
fn motion(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use crate::{
|
|||
CosmicMapped, CosmicSurface, Direction, ManagedLayer,
|
||||
},
|
||||
utils::prelude::*,
|
||||
wayland::protocols::toplevel_info::{toplevel_enter_output, toplevel_enter_workspace},
|
||||
};
|
||||
|
||||
use calloop::LoopHandle;
|
||||
|
|
@ -326,10 +327,10 @@ pub struct MoveGrab {
|
|||
|
||||
impl MoveGrab {
|
||||
fn update_location(&mut self, state: &mut State, location: Point<f64, Logical>) {
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
|
||||
let Some(current_output) =
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
shell
|
||||
.outputs()
|
||||
.find(|output| {
|
||||
output.geometry().as_logical().overlaps_or_touches(
|
||||
|
|
@ -341,9 +342,7 @@ impl MoveGrab {
|
|||
return;
|
||||
};
|
||||
if self.cursor_output != current_output {
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
shell
|
||||
.workspaces
|
||||
.active_mut(&self.cursor_output)
|
||||
.tiling_layer
|
||||
|
|
@ -362,7 +361,7 @@ impl MoveGrab {
|
|||
|
||||
let mut window_geo = self.window.geometry();
|
||||
window_geo.loc += location.to_i32_round() + grab_state.window_offset;
|
||||
for output in state.common.shell.outputs() {
|
||||
for output in shell.outputs() {
|
||||
if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) {
|
||||
if self.window_outputs.insert(output.clone()) {
|
||||
self.window.output_enter(output, overlap);
|
||||
|
|
@ -380,10 +379,7 @@ impl MoveGrab {
|
|||
}
|
||||
}
|
||||
|
||||
let indicator_location = state
|
||||
.common
|
||||
.shell
|
||||
.stacking_indicator(¤t_output, self.previous);
|
||||
let indicator_location = shell.stacking_indicator(¤t_output, self.previous);
|
||||
if indicator_location.is_some() != grab_state.stacking_indicator.is_some() {
|
||||
grab_state.stacking_indicator = indicator_location.map(|geo| {
|
||||
let element = stack_hover(
|
||||
|
|
@ -695,6 +691,13 @@ impl MoveGrab {
|
|||
pub fn is_tiling_grab(&self) -> bool {
|
||||
self.previous == ManagedLayer::Tiling
|
||||
}
|
||||
|
||||
pub fn is_touch_grab(&self) -> bool {
|
||||
match self.start_data {
|
||||
GrabStartData::Touch(_) => true,
|
||||
GrabStartData::Pointer(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MoveGrab {
|
||||
|
|
@ -716,23 +719,17 @@ impl Drop for MoveGrab {
|
|||
if grab_state.window.alive() {
|
||||
let window_location =
|
||||
(grab_state.location.to_i32_round() + grab_state.window_offset).as_global();
|
||||
let mut shell = state.common.shell.write().unwrap();
|
||||
|
||||
let workspace_handle = state.common.shell.active_space(&output).handle;
|
||||
let workspace_handle = shell.active_space(&output).handle;
|
||||
for old_output in window_outputs.iter().filter(|o| *o != &output) {
|
||||
grab_state.window.output_leave(old_output);
|
||||
}
|
||||
|
||||
for (window, _) in grab_state.window.windows() {
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.toplevel_info_state
|
||||
.toplevel_enter_output(&window, &output);
|
||||
toplevel_enter_output(&window, &output);
|
||||
if previous != ManagedLayer::Sticky {
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.toplevel_info_state
|
||||
.toplevel_enter_workspace(&window, &workspace_handle);
|
||||
toplevel_enter_workspace(&window, &workspace_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -742,19 +739,15 @@ impl Drop for MoveGrab {
|
|||
window_location,
|
||||
grab_state.window.geometry().size.as_global(),
|
||||
));
|
||||
let set = state.common.shell.workspaces.sets.get_mut(&output).unwrap();
|
||||
let set = shell.workspaces.sets.get_mut(&output).unwrap();
|
||||
let (window, location) = set
|
||||
.sticky_layer
|
||||
.drop_window(grab_state.window, window_location.to_local(&output));
|
||||
|
||||
Some((window, location.to_global(&output)))
|
||||
}
|
||||
ManagedLayer::Tiling
|
||||
if state.common.shell.active_space(&output).tiling_enabled =>
|
||||
{
|
||||
let (window, location) = state
|
||||
.common
|
||||
.shell
|
||||
ManagedLayer::Tiling if shell.active_space(&output).tiling_enabled => {
|
||||
let (window, location) = shell
|
||||
.active_space_mut(&output)
|
||||
.tiling_layer
|
||||
.drop_window(grab_state.window);
|
||||
|
|
@ -765,8 +758,8 @@ impl Drop for MoveGrab {
|
|||
window_location,
|
||||
grab_state.window.geometry().size.as_global(),
|
||||
));
|
||||
let theme = state.common.shell.theme.clone();
|
||||
let workspace = state.common.shell.active_space_mut(&output);
|
||||
let theme = shell.theme.clone();
|
||||
let workspace = shell.active_space_mut(&output);
|
||||
let (window, location) = workspace.floating_layer.drop_window(
|
||||
grab_state.window,
|
||||
window_location.to_local(&workspace.output),
|
||||
|
|
@ -775,7 +768,7 @@ impl Drop for MoveGrab {
|
|||
if previous == ManagedLayer::Floating {
|
||||
if let Some(sz) = grab_state.snapping_zone {
|
||||
if sz == SnappingZone::Maximize {
|
||||
state.common.shell.maximize_toggle(&window, &seat);
|
||||
shell.maximize_toggle(&window, &seat);
|
||||
} else {
|
||||
let directions = match sz {
|
||||
SnappingZone::Maximize => vec![],
|
||||
|
|
|
|||
|
|
@ -123,6 +123,13 @@ impl ResizeSurfaceGrab {
|
|||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_touch_grab(&self) -> bool {
|
||||
match self.start_data {
|
||||
GrabStartData::Touch(_) => true,
|
||||
GrabStartData::Pointer(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerGrab<State> for ResizeSurfaceGrab {
|
||||
|
|
|
|||
|
|
@ -218,7 +218,8 @@ impl ResizeForkGrab {
|
|||
let delta = location - self.last_loc.as_logical();
|
||||
|
||||
if let Some(output) = self.output.upgrade() {
|
||||
let tiling_layer = &mut data.common.shell.active_space_mut(&output).tiling_layer;
|
||||
let mut shell = data.common.shell.write().unwrap();
|
||||
let tiling_layer = &mut shell.active_space_mut(&output).tiling_layer;
|
||||
let gaps = tiling_layer.gaps();
|
||||
|
||||
let tree = &mut tiling_layer.queue.trees.back_mut().unwrap().0;
|
||||
|
|
@ -321,6 +322,13 @@ impl ResizeForkGrab {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_touch_grab(&self) -> bool {
|
||||
match self.start_data {
|
||||
GrabStartData::Touch(_) => true,
|
||||
GrabStartData::Pointer(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerGrab<State> for ResizeForkGrab {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ impl KeyboardGrab<State> for SwapWindowGrab {
|
|||
serial: Serial,
|
||||
time: u32,
|
||||
) {
|
||||
if !matches!(&data.common.shell.overview_mode, OverviewMode::Started(Trigger::KeyboardSwap(_, d), _) if d == &self.desc)
|
||||
if !matches!(&data.common.shell.read().unwrap().overview_mode, OverviewMode::Started(Trigger::KeyboardSwap(_, d), _) if d == &self.desc)
|
||||
{
|
||||
handle.unset_grab(data, serial, false);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,13 @@ use crate::{
|
|||
utils::{prelude::*, tween::EaseRectangle},
|
||||
wayland::{
|
||||
handlers::xdg_shell::popup::get_popup_toplevel,
|
||||
protocols::{toplevel_info::ToplevelInfoState, workspace::WorkspaceHandle},
|
||||
protocols::{
|
||||
toplevel_info::{
|
||||
toplevel_enter_output, toplevel_enter_workspace, toplevel_leave_output,
|
||||
toplevel_leave_workspace,
|
||||
},
|
||||
workspace::WorkspaceHandle,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -633,7 +639,6 @@ impl TilingLayout {
|
|||
seat: &Seat<State>,
|
||||
focus_stack: impl Iterator<Item = &'a CosmicMapped> + 'a,
|
||||
desc: NodeDesc,
|
||||
toplevel_info_state: &mut ToplevelInfoState<State, CosmicSurface>,
|
||||
) -> Option<KeyboardFocusTarget> {
|
||||
let this_handle = &desc.handle;
|
||||
let mut this_tree = this.queue.trees.back().unwrap().0.copy_clone();
|
||||
|
|
@ -662,13 +667,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&this.output);
|
||||
mapped.output_enter(&other.output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_output(surface, &this.output);
|
||||
toplevel_info_state.toplevel_enter_output(surface, &other.output);
|
||||
toplevel_leave_output(surface, &this.output);
|
||||
toplevel_enter_output(surface, &other.output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_workspace(surface, this_handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(surface, other_handle);
|
||||
toplevel_leave_workspace(surface, this_handle);
|
||||
toplevel_enter_workspace(surface, other_handle);
|
||||
}
|
||||
|
||||
mapped.set_tiled(true);
|
||||
|
|
@ -725,13 +730,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&this.output);
|
||||
mapped.output_enter(&other.output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_output(surface, &this.output);
|
||||
toplevel_info_state.toplevel_enter_output(surface, &other.output);
|
||||
toplevel_leave_output(surface, &this.output);
|
||||
toplevel_enter_output(surface, &other.output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_workspace(surface, this_handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(surface, other_handle);
|
||||
toplevel_leave_workspace(surface, this_handle);
|
||||
toplevel_enter_workspace(surface, other_handle);
|
||||
}
|
||||
|
||||
*mapped.tiling_node_id.lock().unwrap() = Some(id.clone());
|
||||
|
|
@ -759,15 +764,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&this.output);
|
||||
mapped.output_enter(&other.output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state
|
||||
.toplevel_leave_output(surface, &this.output);
|
||||
toplevel_info_state
|
||||
.toplevel_enter_output(surface, &other.output);
|
||||
toplevel_leave_output(surface, &this.output);
|
||||
toplevel_enter_output(surface, &other.output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_workspace(surface, this_handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(surface, other_handle);
|
||||
toplevel_leave_workspace(surface, this_handle);
|
||||
toplevel_enter_workspace(surface, other_handle);
|
||||
}
|
||||
|
||||
*mapped.tiling_node_id.lock().unwrap() = Some(new_id.clone());
|
||||
|
|
@ -806,7 +809,6 @@ impl TilingLayout {
|
|||
mut other: Option<&mut Self>,
|
||||
this_desc: &NodeDesc,
|
||||
other_desc: &NodeDesc,
|
||||
toplevel_info_state: &mut ToplevelInfoState<State, CosmicSurface>,
|
||||
) -> Option<KeyboardFocusTarget> {
|
||||
let other_output = other
|
||||
.as_ref()
|
||||
|
|
@ -860,13 +862,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&other_output);
|
||||
mapped.output_enter(&this.output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_output(surface, &other_output);
|
||||
toplevel_info_state.toplevel_enter_output(surface, &this.output);
|
||||
toplevel_leave_output(surface, &other_output);
|
||||
toplevel_enter_output(surface, &this.output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_workspace(surface, &other_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(surface, &this_desc.handle);
|
||||
toplevel_leave_workspace(surface, &other_desc.handle);
|
||||
toplevel_enter_workspace(surface, &this_desc.handle);
|
||||
}
|
||||
*mapped.tiling_node_id.lock().unwrap() = Some(this_desc.node.clone());
|
||||
}
|
||||
|
|
@ -875,13 +877,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&this.output);
|
||||
mapped.output_enter(&other_output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_output(surface, &this.output);
|
||||
toplevel_info_state.toplevel_enter_output(surface, &other_output);
|
||||
toplevel_leave_output(surface, &this.output);
|
||||
toplevel_enter_output(surface, &other_output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state.toplevel_leave_workspace(surface, &this_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(surface, &other_desc.handle);
|
||||
toplevel_leave_workspace(surface, &this_desc.handle);
|
||||
toplevel_enter_workspace(surface, &other_desc.handle);
|
||||
}
|
||||
*mapped.tiling_node_id.lock().unwrap() = Some(other_desc.node.clone());
|
||||
}
|
||||
|
|
@ -914,17 +916,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&this.output);
|
||||
mapped.output_enter(&other_output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state
|
||||
.toplevel_leave_output(surface, &this.output);
|
||||
toplevel_info_state
|
||||
.toplevel_enter_output(surface, &other_output);
|
||||
toplevel_leave_output(surface, &this.output);
|
||||
toplevel_enter_output(surface, &other_output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state
|
||||
.toplevel_leave_workspace(surface, &this_desc.handle);
|
||||
toplevel_info_state
|
||||
.toplevel_enter_workspace(surface, &other_desc.handle);
|
||||
toplevel_leave_workspace(surface, &this_desc.handle);
|
||||
toplevel_enter_workspace(surface, &other_desc.handle);
|
||||
}
|
||||
*mapped.tiling_node_id.lock().unwrap() = Some(new_id.clone());
|
||||
}
|
||||
|
|
@ -964,17 +962,13 @@ impl TilingLayout {
|
|||
mapped.output_leave(&other_output);
|
||||
mapped.output_enter(&this.output, mapped.bbox());
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state
|
||||
.toplevel_leave_output(surface, &other_output);
|
||||
toplevel_info_state
|
||||
.toplevel_enter_output(surface, &this.output);
|
||||
toplevel_leave_output(surface, &other_output);
|
||||
toplevel_enter_output(surface, &this.output);
|
||||
}
|
||||
}
|
||||
for (ref surface, _) in mapped.windows() {
|
||||
toplevel_info_state
|
||||
.toplevel_leave_workspace(surface, &other_desc.handle);
|
||||
toplevel_info_state
|
||||
.toplevel_enter_workspace(surface, &this_desc.handle);
|
||||
toplevel_leave_workspace(surface, &other_desc.handle);
|
||||
toplevel_enter_workspace(surface, &this_desc.handle);
|
||||
}
|
||||
*mapped.tiling_node_id.lock().unwrap() = Some(new_id.clone());
|
||||
}
|
||||
|
|
@ -1034,23 +1028,23 @@ impl TilingLayout {
|
|||
if this.output != other_output {
|
||||
surface.output_leave(&other_output);
|
||||
surface.output_enter(&this.output, surface.bbox());
|
||||
toplevel_info_state.toplevel_leave_output(&surface, &other_output);
|
||||
toplevel_info_state.toplevel_enter_output(&surface, &this.output);
|
||||
toplevel_leave_output(&surface, &other_output);
|
||||
toplevel_enter_output(&surface, &this.output);
|
||||
}
|
||||
if this_desc.handle != other_desc.handle {
|
||||
toplevel_info_state.toplevel_leave_workspace(&surface, &other_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(&surface, &this_desc.handle);
|
||||
toplevel_leave_workspace(&surface, &other_desc.handle);
|
||||
toplevel_enter_workspace(&surface, &this_desc.handle);
|
||||
}
|
||||
this_stack.add_window(surface, Some(this_idx + i));
|
||||
}
|
||||
if this.output != other_output {
|
||||
this_surface.output_leave(&this.output);
|
||||
toplevel_info_state.toplevel_leave_output(&this_surface, &this.output);
|
||||
toplevel_info_state.toplevel_enter_output(&this_surface, &other_output);
|
||||
toplevel_leave_output(this_surface, &this.output);
|
||||
toplevel_enter_output(this_surface, &other_output);
|
||||
}
|
||||
if this_desc.handle != other_desc.handle {
|
||||
toplevel_info_state.toplevel_leave_workspace(&this_surface, &this_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(&this_surface, &other_desc.handle);
|
||||
toplevel_leave_workspace(this_surface, &this_desc.handle);
|
||||
toplevel_enter_workspace(this_surface, &other_desc.handle);
|
||||
}
|
||||
this_stack.remove_window(&this_surface);
|
||||
|
||||
|
|
@ -1121,24 +1115,23 @@ impl TilingLayout {
|
|||
if this.output != other_output {
|
||||
surface.output_leave(&this.output);
|
||||
surface.output_enter(&other_output, surface.bbox());
|
||||
toplevel_info_state.toplevel_leave_output(&surface, &this.output);
|
||||
toplevel_info_state.toplevel_enter_output(&surface, &other_output);
|
||||
toplevel_leave_output(&surface, &this.output);
|
||||
toplevel_enter_output(&surface, &other_output);
|
||||
}
|
||||
if this_desc.handle != other_desc.handle {
|
||||
toplevel_info_state.toplevel_leave_workspace(&surface, &this_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(&surface, &other_desc.handle);
|
||||
toplevel_leave_workspace(&surface, &this_desc.handle);
|
||||
toplevel_enter_workspace(&surface, &other_desc.handle);
|
||||
}
|
||||
other_stack.add_window(surface, Some(other_idx + i));
|
||||
}
|
||||
if this.output != other_output {
|
||||
other_surface.output_leave(&other_output);
|
||||
toplevel_info_state.toplevel_leave_output(&other_surface, &other_output);
|
||||
toplevel_info_state.toplevel_enter_output(&other_surface, &this.output);
|
||||
toplevel_leave_output(other_surface, &other_output);
|
||||
toplevel_enter_output(other_surface, &this.output);
|
||||
}
|
||||
if this_desc.handle != other_desc.handle {
|
||||
toplevel_info_state
|
||||
.toplevel_leave_workspace(&other_surface, &other_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(&other_surface, &this_desc.handle);
|
||||
toplevel_leave_workspace(other_surface, &other_desc.handle);
|
||||
toplevel_enter_workspace(other_surface, &this_desc.handle);
|
||||
}
|
||||
other_stack.remove_window(&other_surface);
|
||||
|
||||
|
|
@ -1205,17 +1198,16 @@ impl TilingLayout {
|
|||
other_stack.add_window(this_surface.clone(), Some(other_idx));
|
||||
|
||||
if this.output != other_output {
|
||||
toplevel_info_state.toplevel_leave_output(&this_surface, &this.output);
|
||||
toplevel_info_state.toplevel_leave_output(&other_surface, &other_output);
|
||||
toplevel_info_state.toplevel_enter_output(&this_surface, &other_output);
|
||||
toplevel_info_state.toplevel_enter_output(&other_surface, &this.output);
|
||||
toplevel_leave_output(this_surface, &this.output);
|
||||
toplevel_leave_output(other_surface, &other_output);
|
||||
toplevel_enter_output(this_surface, &other_output);
|
||||
toplevel_enter_output(other_surface, &this.output);
|
||||
}
|
||||
if this_desc.handle != other_desc.handle {
|
||||
toplevel_info_state.toplevel_leave_workspace(&this_surface, &this_desc.handle);
|
||||
toplevel_info_state
|
||||
.toplevel_leave_workspace(&other_surface, &other_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(&this_surface, &other_desc.handle);
|
||||
toplevel_info_state.toplevel_enter_workspace(&other_surface, &this_desc.handle);
|
||||
toplevel_leave_workspace(this_surface, &this_desc.handle);
|
||||
toplevel_leave_workspace(other_surface, &other_desc.handle);
|
||||
toplevel_enter_workspace(this_surface, &other_desc.handle);
|
||||
toplevel_enter_workspace(other_surface, &this_desc.handle);
|
||||
}
|
||||
|
||||
other_stack.remove_window(&other_surface);
|
||||
|
|
@ -1802,7 +1794,7 @@ impl TilingLayout {
|
|||
}
|
||||
|
||||
pub fn next_focus<'a>(
|
||||
&mut self,
|
||||
&self,
|
||||
direction: FocusDirection,
|
||||
seat: &Seat<State>,
|
||||
focus_stack: impl Iterator<Item = &'a CosmicMapped> + 'a,
|
||||
|
|
|
|||
1369
src/shell/mod.rs
1369
src/shell/mod.rs
File diff suppressed because it is too large
Load diff
|
|
@ -206,6 +206,8 @@ pub trait SeatExt {
|
|||
fn active_output(&self) -> Output;
|
||||
fn set_active_output(&self, output: &Output);
|
||||
fn devices(&self) -> &Devices;
|
||||
fn supressed_keys(&self) -> &SupressedKeys;
|
||||
fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue;
|
||||
|
||||
fn cursor_geometry(
|
||||
&self,
|
||||
|
|
@ -239,6 +241,14 @@ impl SeatExt for Seat<State> {
|
|||
self.user_data().get::<Devices>().unwrap()
|
||||
}
|
||||
|
||||
fn supressed_keys(&self) -> &SupressedKeys {
|
||||
self.user_data().get::<SupressedKeys>().unwrap()
|
||||
}
|
||||
|
||||
fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue {
|
||||
self.user_data().get::<ModifiersShortcutQueue>().unwrap()
|
||||
}
|
||||
|
||||
fn cursor_geometry(
|
||||
&self,
|
||||
loc: impl Into<Point<f64, Buffer>>,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
wayland::{
|
||||
handlers::screencopy::ScreencopySessions,
|
||||
protocols::{
|
||||
toplevel_info::ToplevelInfoState,
|
||||
toplevel_info::{toplevel_enter_output, toplevel_leave_output},
|
||||
workspace::{WorkspaceHandle, WorkspaceUpdateGuard},
|
||||
},
|
||||
},
|
||||
|
|
@ -365,23 +365,19 @@ impl Workspace {
|
|||
&self.output
|
||||
}
|
||||
|
||||
pub fn set_output(
|
||||
&mut self,
|
||||
output: &Output,
|
||||
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
||||
) {
|
||||
pub fn set_output(&mut self, output: &Output) {
|
||||
self.tiling_layer.set_output(output);
|
||||
self.floating_layer.set_output(output);
|
||||
for mapped in self.mapped() {
|
||||
for (surface, _) in mapped.windows() {
|
||||
toplevel_info.toplevel_leave_output(&surface, &self.output);
|
||||
toplevel_info.toplevel_enter_output(&surface, output);
|
||||
toplevel_leave_output(&surface, &self.output);
|
||||
toplevel_enter_output(&surface, output);
|
||||
}
|
||||
}
|
||||
for window in self.minimized_windows.iter() {
|
||||
for (surface, _) in window.window.windows() {
|
||||
toplevel_info.toplevel_leave_output(&surface, &self.output);
|
||||
toplevel_info.toplevel_enter_output(&surface, output);
|
||||
toplevel_leave_output(&surface, &self.output);
|
||||
toplevel_enter_output(&surface, output);
|
||||
}
|
||||
}
|
||||
let output_name = output.name();
|
||||
|
|
|
|||
107
src/state.rs
107
src/state.rs
|
|
@ -4,12 +4,17 @@ use crate::{
|
|||
backend::{kms::KmsState, winit::WinitState, x11::X11State},
|
||||
config::{Config, OutputConfig},
|
||||
input::gestures::GestureState,
|
||||
shell::{grabs::SeatMoveGrabState, SeatExt, Shell},
|
||||
shell::{grabs::SeatMoveGrabState, CosmicSurface, SeatExt, Shell},
|
||||
wayland::protocols::{
|
||||
drm::WlDrmState, image_source::ImageSourceState,
|
||||
output_configuration::OutputConfigurationState, screencopy::ScreencopyState,
|
||||
workspace::WorkspaceClientState,
|
||||
drm::WlDrmState,
|
||||
image_source::ImageSourceState,
|
||||
output_configuration::OutputConfigurationState,
|
||||
screencopy::ScreencopyState,
|
||||
toplevel_info::ToplevelInfoState,
|
||||
toplevel_management::{ManagementCapabilities, ToplevelManagementState},
|
||||
workspace::{WorkspaceClientState, WorkspaceState, WorkspaceUpdateGuard},
|
||||
},
|
||||
xwayland::XWaylandState,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use i18n_embed::{
|
||||
|
|
@ -41,11 +46,13 @@ use smithay::{
|
|||
take_presentation_feedback_surface_tree, update_surface_primary_scanout_output,
|
||||
with_surfaces_surface_tree, OutputPresentationFeedback,
|
||||
},
|
||||
PopupManager,
|
||||
},
|
||||
input::{pointer::CursorImageStatus, SeatState},
|
||||
output::{Mode as OutputMode, Output, Scale},
|
||||
reexports::{
|
||||
calloop::{LoopHandle, LoopSignal},
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel::WmCapabilities,
|
||||
wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode,
|
||||
wayland_server::{
|
||||
backend::{ClientData, ClientId, DisconnectReason},
|
||||
|
|
@ -71,12 +78,17 @@ use smithay::{
|
|||
wlr_data_control::DataControlState,
|
||||
},
|
||||
session_lock::SessionLockManagerState,
|
||||
shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState},
|
||||
shell::{
|
||||
kde::decoration::KdeDecorationState,
|
||||
wlr_layer::WlrLayerShellState,
|
||||
xdg::{decoration::XdgDecorationState, XdgShellState},
|
||||
},
|
||||
shm::ShmState,
|
||||
tablet_manager::TabletManagerState,
|
||||
text_input::TextInputManagerState,
|
||||
viewporter::ViewporterState,
|
||||
virtual_keyboard::VirtualKeyboardManagerState,
|
||||
xdg_activation::XdgActivationState,
|
||||
xwayland_keyboard_grab::XWaylandKeyboardGrabState,
|
||||
},
|
||||
xwayland::XWaylandClientData,
|
||||
|
|
@ -84,6 +96,7 @@ use smithay::{
|
|||
use time::UtcOffset;
|
||||
use tracing::error;
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::{cell::RefCell, ffi::OsString, time::Duration};
|
||||
use std::{collections::VecDeque, time::Instant};
|
||||
|
||||
|
|
@ -147,7 +160,8 @@ pub struct Common {
|
|||
pub event_loop_handle: LoopHandle<'static, State>,
|
||||
pub event_loop_signal: LoopSignal,
|
||||
|
||||
pub shell: Shell,
|
||||
pub popups: PopupManager,
|
||||
pub shell: Arc<RwLock<Shell>>,
|
||||
|
||||
pub clock: Clock<Monotonic>,
|
||||
pub should_stop: bool,
|
||||
|
|
@ -179,6 +193,15 @@ pub struct Common {
|
|||
pub viewporter_state: ViewporterState,
|
||||
pub kde_decoration_state: KdeDecorationState,
|
||||
pub xdg_decoration_state: XdgDecorationState,
|
||||
|
||||
// shell-related wayland state
|
||||
pub xdg_shell_state: XdgShellState,
|
||||
pub layer_shell_state: WlrLayerShellState,
|
||||
pub toplevel_info_state: ToplevelInfoState<State, CosmicSurface>,
|
||||
pub toplevel_management_state: ToplevelManagementState,
|
||||
pub xdg_activation_state: XdgActivationState,
|
||||
pub workspace_state: WorkspaceState<State>,
|
||||
pub xwayland_state: Option<XWaylandState>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -225,11 +248,18 @@ impl BackendData {
|
|||
test_only: bool,
|
||||
shell: &mut Shell,
|
||||
loop_handle: &LoopHandle<'_, State>,
|
||||
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
|
||||
xdg_activation_state: &XdgActivationState,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let result = match self {
|
||||
BackendData::Kms(ref mut state) => {
|
||||
state.apply_config_for_output(output, shell, test_only, loop_handle)
|
||||
}
|
||||
BackendData::Kms(ref mut state) => state.apply_config_for_output(
|
||||
output,
|
||||
shell,
|
||||
test_only,
|
||||
loop_handle,
|
||||
workspace_state,
|
||||
xdg_activation_state,
|
||||
),
|
||||
BackendData::Winit(ref mut state) => state.apply_config_for_output(output, test_only),
|
||||
BackendData::X11(ref mut state) => state.apply_config_for_output(output, test_only),
|
||||
_ => unreachable!("No backend set when applying output config"),
|
||||
|
|
@ -389,7 +419,36 @@ impl State {
|
|||
DataControlState::new::<Self, _>(dh, Some(&primary_selection_state), |_| true)
|
||||
});
|
||||
|
||||
let shell = Shell::new(&config, dh);
|
||||
let shell = Arc::new(RwLock::new(Shell::new(&config)));
|
||||
|
||||
let layer_shell_state = WlrLayerShellState::new_with_filter::<State, _>(
|
||||
dh,
|
||||
client_should_see_privileged_protocols,
|
||||
);
|
||||
let xdg_shell_state = XdgShellState::new_with_capabilities::<State>(
|
||||
dh,
|
||||
[
|
||||
WmCapabilities::Fullscreen,
|
||||
WmCapabilities::Maximize,
|
||||
WmCapabilities::Minimize,
|
||||
WmCapabilities::WindowMenu,
|
||||
],
|
||||
);
|
||||
let xdg_activation_state = XdgActivationState::new::<State>(dh);
|
||||
let toplevel_info_state =
|
||||
ToplevelInfoState::new(dh, client_should_see_privileged_protocols);
|
||||
let toplevel_management_state = ToplevelManagementState::new::<State, _>(
|
||||
dh,
|
||||
vec![
|
||||
ManagementCapabilities::Close,
|
||||
ManagementCapabilities::Activate,
|
||||
ManagementCapabilities::Maximize,
|
||||
ManagementCapabilities::Minimize,
|
||||
ManagementCapabilities::MoveToWorkspace,
|
||||
],
|
||||
client_should_see_privileged_protocols,
|
||||
);
|
||||
let workspace_state = WorkspaceState::new(dh, client_should_see_privileged_protocols);
|
||||
|
||||
if let Err(err) = crate::dbus::init(&handle) {
|
||||
tracing::warn!(?err, "Failed to initialize dbus handlers");
|
||||
|
|
@ -403,6 +462,7 @@ impl State {
|
|||
event_loop_handle: handle,
|
||||
event_loop_signal: signal,
|
||||
|
||||
popups: PopupManager::default(),
|
||||
shell,
|
||||
|
||||
local_offset,
|
||||
|
|
@ -441,6 +501,13 @@ impl State {
|
|||
wl_drm_state,
|
||||
kde_decoration_state,
|
||||
xdg_decoration_state,
|
||||
xdg_shell_state,
|
||||
layer_shell_state,
|
||||
toplevel_info_state,
|
||||
toplevel_management_state,
|
||||
xdg_activation_state,
|
||||
workspace_state,
|
||||
xwayland_state: None,
|
||||
},
|
||||
backend: BackendData::Unset,
|
||||
}
|
||||
|
|
@ -495,8 +562,9 @@ impl Common {
|
|||
) {
|
||||
let time = self.clock.now();
|
||||
let throttle = Some(Duration::from_secs(1));
|
||||
let shell = self.shell.read().unwrap();
|
||||
|
||||
if let Some(session_lock) = self.shell.session_lock.as_ref() {
|
||||
if let Some(session_lock) = shell.session_lock.as_ref() {
|
||||
if let Some(lock_surface) = session_lock.surfaces.get(output) {
|
||||
with_surfaces_surface_tree(lock_surface.wl_surface(), |_surface, states| {
|
||||
with_fractional_scale(states, |fraction_scale| {
|
||||
|
|
@ -532,8 +600,7 @@ impl Common {
|
|||
}
|
||||
}
|
||||
|
||||
for seat in self
|
||||
.shell
|
||||
for seat in shell
|
||||
.seats
|
||||
.iter()
|
||||
.filter(|seat| &seat.active_output() == output)
|
||||
|
|
@ -595,7 +662,7 @@ impl Common {
|
|||
}
|
||||
}
|
||||
|
||||
self.shell
|
||||
shell
|
||||
.workspaces
|
||||
.sets
|
||||
.get(output)
|
||||
|
|
@ -636,7 +703,7 @@ impl Common {
|
|||
}
|
||||
});
|
||||
|
||||
let active = self.shell.active_space(output);
|
||||
let active = shell.active_space(output);
|
||||
active.mapped().for_each(|mapped| {
|
||||
let window = mapped.active_window();
|
||||
window.with_surfaces(|surface, states| {
|
||||
|
|
@ -675,8 +742,7 @@ impl Common {
|
|||
window.send_frame(output, time, throttle, |_, _| None);
|
||||
});
|
||||
|
||||
for space in self
|
||||
.shell
|
||||
for space in shell
|
||||
.workspaces
|
||||
.spaces_for_output(output)
|
||||
.filter(|w| w.handle != active.handle)
|
||||
|
|
@ -691,7 +757,7 @@ impl Common {
|
|||
})
|
||||
}
|
||||
|
||||
self.shell.override_redirect_windows.iter().for_each(|or| {
|
||||
shell.override_redirect_windows.iter().for_each(|or| {
|
||||
if let Some(wl_surface) = or.wl_surface() {
|
||||
with_surfaces_surface_tree(&wl_surface, |surface, states| {
|
||||
let primary_scanout_output = update_surface_primary_scanout_output(
|
||||
|
|
@ -780,8 +846,9 @@ impl Common {
|
|||
render_element_states: &RenderElementStates,
|
||||
) -> OutputPresentationFeedback {
|
||||
let mut output_presentation_feedback = OutputPresentationFeedback::new(output);
|
||||
let shell = self.shell.read().unwrap();
|
||||
|
||||
let active = self.shell.active_space(output);
|
||||
let active = shell.active_space(output);
|
||||
active.mapped().for_each(|mapped| {
|
||||
mapped.active_window().take_presentation_feedback(
|
||||
&mut output_presentation_feedback,
|
||||
|
|
@ -792,7 +859,7 @@ impl Common {
|
|||
);
|
||||
});
|
||||
|
||||
self.shell.override_redirect_windows.iter().for_each(|or| {
|
||||
shell.override_redirect_windows.iter().for_each(|or| {
|
||||
if let Some(wl_surface) = or.wl_surface() {
|
||||
take_presentation_feedback_surface_tree(
|
||||
&wl_surface,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ pub fn ready(state: &State) {
|
|||
"DISPLAY",
|
||||
&state
|
||||
.common
|
||||
.shell
|
||||
.xwayland_state
|
||||
.as_ref()
|
||||
.map(|s| format!(":{}", s.display))
|
||||
|
|
|
|||
13
src/theme.rs
13
src/theme.rs
|
|
@ -32,13 +32,12 @@ pub fn watch_theme(handle: LoopHandle<'_, State>) -> Result<(), cosmic_config::E
|
|||
|
||||
if theme.theme_type != new_theme.theme_type {
|
||||
*theme = new_theme;
|
||||
state.common.shell.set_theme(theme.clone());
|
||||
state.common.shell.workspaces.spaces().for_each(|s| {
|
||||
s.mapped().for_each(|m| {
|
||||
m.update_theme(theme.clone());
|
||||
m.force_redraw();
|
||||
})
|
||||
});
|
||||
let mut workspace_guard = state.common.workspace_state.update();
|
||||
state.common.shell.write().unwrap().set_theme(
|
||||
theme.clone(),
|
||||
&state.common.xdg_activation_state,
|
||||
&mut workspace_guard,
|
||||
);
|
||||
}
|
||||
}) {
|
||||
tracing::error!("{e}");
|
||||
|
|
|
|||
|
|
@ -26,66 +26,57 @@ use smithay::{
|
|||
};
|
||||
use std::sync::Mutex;
|
||||
|
||||
impl State {
|
||||
fn toplevel_ensure_initial_configure(&mut self, toplevel: &ToplevelSurface) -> bool {
|
||||
// send the initial configure if relevant
|
||||
let initial_configure_sent = with_states(toplevel.wl_surface(), |states| {
|
||||
fn toplevel_ensure_initial_configure(toplevel: &ToplevelSurface) -> bool {
|
||||
// send the initial configure if relevant
|
||||
let initial_configure_sent = with_states(toplevel.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if !initial_configure_sent {
|
||||
// TODO: query expected size from shell (without inserting and mapping)
|
||||
toplevel.with_pending_state(|states| states.size = None);
|
||||
toplevel.send_configure();
|
||||
}
|
||||
initial_configure_sent
|
||||
}
|
||||
|
||||
fn xdg_popup_ensure_initial_configure(popup: &PopupKind) {
|
||||
if let PopupKind::Xdg(ref popup) = popup {
|
||||
let initial_configure_sent = with_states(popup.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
|
||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if !initial_configure_sent {
|
||||
// TODO: query expected size from shell (without inserting and mapping)
|
||||
toplevel.with_pending_state(|states| states.size = None);
|
||||
toplevel.send_configure();
|
||||
// NOTE: This should never fail as the initial configure is always
|
||||
// allowed.
|
||||
popup.send_configure().expect("initial configure failed");
|
||||
}
|
||||
initial_configure_sent
|
||||
}
|
||||
}
|
||||
|
||||
fn xdg_popup_ensure_initial_configure(&mut self, popup: &PopupKind) {
|
||||
if let PopupKind::Xdg(ref popup) = popup {
|
||||
let initial_configure_sent = with_states(popup.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if !initial_configure_sent {
|
||||
// NOTE: This should never fail as the initial configure is always
|
||||
// allowed.
|
||||
popup.send_configure().expect("initial configure failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
fn layer_surface_check_inital_configure(surface: &LayerSurface) -> bool {
|
||||
// send the initial configure if relevant
|
||||
let initial_configure_sent = with_states(surface.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<LayerSurfaceAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
|
||||
fn layer_surface_ensure_inital_configure(&mut self, surface: &LayerSurface) -> bool {
|
||||
// send the initial configure if relevant
|
||||
let initial_configure_sent = with_states(surface.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<LayerSurfaceAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if !initial_configure_sent {
|
||||
// compute initial dimensions by mapping
|
||||
if let Some(target) = self.common.shell.map_layer(&surface) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
Shell::set_focus(self, Some(&target), &seat, None);
|
||||
}
|
||||
surface.layer_surface().send_configure();
|
||||
}
|
||||
initial_configure_sent
|
||||
}
|
||||
initial_configure_sent
|
||||
}
|
||||
|
||||
pub fn client_compositor_state<'a>(client: &'a Client) -> &'a CompositorClientState {
|
||||
|
|
@ -147,48 +138,67 @@ impl CompositorHandler for State {
|
|||
// first load the buffer for various smithay helper functions (which also initializes the RendererSurfaceState)
|
||||
on_commit_buffer_handler::<Self>(surface);
|
||||
|
||||
// and refresh smithays internal state
|
||||
self.common.on_commit(surface);
|
||||
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
||||
// schedule a new render
|
||||
if let Some(output) = shell.visible_output_for_surface(surface) {
|
||||
self.backend
|
||||
.schedule_render(&self.common.event_loop_handle, &output);
|
||||
}
|
||||
|
||||
// handle initial configure events and map windows if necessary
|
||||
if let Some((window, _, _)) = self
|
||||
.common
|
||||
.shell
|
||||
if let Some((window, _, _)) = shell
|
||||
.pending_windows
|
||||
.iter()
|
||||
.find(|(window, _, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
.cloned()
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
if self.toplevel_ensure_initial_configure(&toplevel)
|
||||
if toplevel_ensure_initial_configure(&toplevel)
|
||||
&& with_renderer_surface_state(&surface, |state| state.buffer().is_some())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
window.on_commit();
|
||||
if let Some(target) = self.common.shell.map_window(
|
||||
let res = shell.map_window(
|
||||
&window,
|
||||
&mut self.common.toplevel_info_state,
|
||||
&mut self.common.workspace_state,
|
||||
&self.common.event_loop_handle,
|
||||
&self.common.theme,
|
||||
) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
);
|
||||
if let Some(target) = res {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((layer_surface, _, _)) = self
|
||||
.common
|
||||
.shell
|
||||
if let Some((layer_surface, _, _)) = shell
|
||||
.pending_layers
|
||||
.iter()
|
||||
.find(|(layer_surface, _, _)| layer_surface.wl_surface() == surface)
|
||||
.cloned()
|
||||
{
|
||||
if !self.layer_surface_ensure_inital_configure(&layer_surface) {
|
||||
if !layer_surface_check_inital_configure(&layer_surface) {
|
||||
// compute initial dimensions by mapping
|
||||
if let Some(target) = shell.map_layer(&layer_surface) {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None);
|
||||
}
|
||||
layer_surface.layer_surface().send_configure();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(popup) = self.common.shell.popups.find_popup(surface) {
|
||||
self.xdg_popup_ensure_initial_configure(&popup);
|
||||
if let Some(popup) = self.common.popups.find_popup(surface) {
|
||||
xdg_popup_ensure_initial_configure(&popup);
|
||||
return;
|
||||
}
|
||||
|
||||
if with_renderer_surface_state(surface, |state| state.buffer().is_none()).unwrap_or(false) {
|
||||
|
|
@ -197,7 +207,7 @@ impl CompositorHandler for State {
|
|||
// session-lock disallows null commits
|
||||
|
||||
// if it was a move-grab?
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let moved_window = seat
|
||||
.user_data()
|
||||
.get::<SeatMoveGrabState>()
|
||||
|
|
@ -228,9 +238,11 @@ impl CompositorHandler for State {
|
|||
stack.remove_idx(i);
|
||||
}
|
||||
} else {
|
||||
std::mem::drop(shell);
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.unset_grab(self, SERIAL_COUNTER.next_serial(), 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,21 +259,16 @@ impl CompositorHandler for State {
|
|||
// If we would re-position the window inside the grab we would get a weird jittery animation.
|
||||
// We only want to resize once the client has acknoledged & commited the new size,
|
||||
// so we need to carefully track the state through different handlers.
|
||||
if let Some(element) = self.common.shell.element_for_surface(surface).cloned() {
|
||||
if let Some(element) = shell.element_for_surface(surface).cloned() {
|
||||
crate::shell::layout::floating::ResizeSurfaceGrab::apply_resize_to_location(
|
||||
element.clone(),
|
||||
&mut self.common.shell,
|
||||
&mut *shell,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// and refresh smithays internal state
|
||||
self.common.shell.on_commit(surface);
|
||||
|
||||
// re-arrange layer-surfaces (commits may change size and positioning)
|
||||
let layer_output = self
|
||||
.common
|
||||
.shell
|
||||
let layer_output = shell
|
||||
.outputs()
|
||||
.find(|o| {
|
||||
let map = layer_map_for_output(o);
|
||||
|
|
@ -269,18 +276,13 @@ impl CompositorHandler for State {
|
|||
.is_some()
|
||||
})
|
||||
.cloned();
|
||||
|
||||
if let Some(output) = layer_output {
|
||||
let changed = layer_map_for_output(&output).arrange();
|
||||
if changed {
|
||||
self.common.shell.workspaces.recalculate();
|
||||
shell.workspaces.recalculate();
|
||||
}
|
||||
}
|
||||
|
||||
// schedule a new render
|
||||
if let Some(output) = self.common.shell.visible_output_for_surface(surface) {
|
||||
self.backend
|
||||
.schedule_render(&self.common.event_loop_handle, &output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,86 +54,85 @@ impl PreferredDecorationMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode {
|
||||
if mapped.is_stack() {
|
||||
if let Some((window, _)) = mapped
|
||||
.windows()
|
||||
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(XdgMode::ServerSide)
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
KdeMode::Server
|
||||
} else {
|
||||
if let Some((window, _)) = mapped
|
||||
.windows()
|
||||
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(XdgMode::ClientSide)
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
KdeMode::Client
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request_mode(mapped: &CosmicMapped, surface: &WlSurface, mode: XdgMode) {
|
||||
pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode {
|
||||
if mapped.is_stack() {
|
||||
if let Some((window, _)) = mapped
|
||||
.windows()
|
||||
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
PreferredDecorationMode::update(&window.0, Some(mode));
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(mode);
|
||||
});
|
||||
toplevel
|
||||
.with_pending_state(|state| state.decoration_mode = Some(XdgMode::ServerSide));
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unset_mode(mapped: &CosmicMapped, surface: &WlSurface) {
|
||||
KdeMode::Server
|
||||
} else {
|
||||
if let Some((window, _)) = mapped
|
||||
.windows()
|
||||
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
PreferredDecorationMode::update(&window.0, None);
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = None;
|
||||
});
|
||||
toplevel
|
||||
.with_pending_state(|state| state.decoration_mode = Some(XdgMode::ClientSide));
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
KdeMode::Client
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request_mode(mapped: &CosmicMapped, surface: &WlSurface, mode: XdgMode) {
|
||||
if let Some((window, _)) = mapped
|
||||
.windows()
|
||||
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
PreferredDecorationMode::update(&window.0, Some(mode));
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(mode);
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unset_mode(mapped: &CosmicMapped, surface: &WlSurface) {
|
||||
if let Some((window, _)) = mapped
|
||||
.windows()
|
||||
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||
{
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
PreferredDecorationMode::update(&window.0, None);
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = None;
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgDecorationHandler for State {
|
||||
fn new_decoration(&mut self, toplevel: ToplevelSurface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(toplevel.wl_surface()) {
|
||||
State::new_decoration(mapped, toplevel.wl_surface());
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(toplevel.wl_surface()) {
|
||||
new_decoration(mapped, toplevel.wl_surface());
|
||||
}
|
||||
}
|
||||
|
||||
fn request_mode(&mut self, toplevel: ToplevelSurface, mode: XdgMode) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(toplevel.wl_surface()) {
|
||||
State::request_mode(mapped, toplevel.wl_surface(), mode);
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(toplevel.wl_surface()) {
|
||||
request_mode(mapped, toplevel.wl_surface(), mode);
|
||||
} else {
|
||||
toplevel.with_pending_state(|state| state.decoration_mode = Some(mode));
|
||||
}
|
||||
}
|
||||
|
||||
fn unset_mode(&mut self, toplevel: ToplevelSurface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(toplevel.wl_surface()) {
|
||||
State::unset_mode(mapped, toplevel.wl_surface())
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(toplevel.wl_surface()) {
|
||||
unset_mode(mapped, toplevel.wl_surface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -144,8 +143,9 @@ impl KdeDecorationHandler for State {
|
|||
}
|
||||
|
||||
fn new_decoration(&mut self, surface: &WlSurface, decoration: &OrgKdeKwinServerDecoration) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(surface) {
|
||||
let mode = State::new_decoration(mapped, surface);
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(surface) {
|
||||
let mode = new_decoration(mapped, surface);
|
||||
decoration.mode(mode);
|
||||
}
|
||||
}
|
||||
|
|
@ -157,9 +157,10 @@ impl KdeDecorationHandler for State {
|
|||
mode: WEnum<KdeMode>,
|
||||
) {
|
||||
if let WEnum::Value(mode) = mode {
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
// TODO: We need to store this value until it gets mapped and apply it then, if it is not mapped yet.
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(surface) {
|
||||
State::request_mode(
|
||||
if let Some(mapped) = shell.element_for_surface(surface) {
|
||||
request_mode(
|
||||
mapped,
|
||||
surface,
|
||||
match mode {
|
||||
|
|
@ -173,8 +174,9 @@ impl KdeDecorationHandler for State {
|
|||
}
|
||||
|
||||
fn release(&mut self, _decoration: &OrgKdeKwinServerDecoration, surface: &WlSurface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(surface) {
|
||||
State::unset_mode(mapped, surface)
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(surface) {
|
||||
unset_mode(mapped, surface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,21 @@ impl FractionalScaleHandler for State {
|
|||
.or_else(|| {
|
||||
self.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.visible_output_for_surface(&surface)
|
||||
.cloned()
|
||||
})
|
||||
})
|
||||
.unwrap_or_else(|| self.common.shell.seats.last_active().active_output());
|
||||
.unwrap_or_else(|| {
|
||||
self.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.active_output()
|
||||
});
|
||||
|
||||
with_states(&surface, |states| {
|
||||
with_fractional_scale(states, |fractional_scale| {
|
||||
|
|
|
|||
|
|
@ -12,12 +12,7 @@ use tracing::warn;
|
|||
|
||||
impl InputMethodHandler for State {
|
||||
fn new_popup(&mut self, surface: PopupSurface) {
|
||||
if let Err(err) = self
|
||||
.common
|
||||
.shell
|
||||
.popups
|
||||
.track_popup(PopupKind::from(surface))
|
||||
{
|
||||
if let Err(err) = self.common.popups.track_popup(PopupKind::from(surface)) {
|
||||
warn!("Failed to track popup: {}", err);
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +26,8 @@ impl InputMethodHandler for State {
|
|||
fn parent_geometry(&self, parent: &WlSurface) -> Rectangle<i32, smithay::utils::Logical> {
|
||||
self.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.element_for_surface(parent)
|
||||
.map(|e| e.geometry())
|
||||
.unwrap_or_default()
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use smithay::{
|
|||
|
||||
impl WlrLayerShellHandler for State {
|
||||
fn shell_state(&mut self) -> &mut WlrLayerShellState {
|
||||
&mut self.common.shell.layer_shell_state
|
||||
&mut self.common.layer_shell_state
|
||||
}
|
||||
|
||||
fn new_layer_surface(
|
||||
|
|
@ -26,24 +26,22 @@ impl WlrLayerShellHandler for State {
|
|||
_layer: Layer,
|
||||
namespace: String,
|
||||
) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let output = wl_output
|
||||
.as_ref()
|
||||
.and_then(Output::from_resource)
|
||||
.unwrap_or_else(|| seat.active_output());
|
||||
self.common.shell.pending_layers.push((
|
||||
LayerSurface::new(surface, namespace),
|
||||
output,
|
||||
seat,
|
||||
));
|
||||
shell
|
||||
.pending_layers
|
||||
.push((LayerSurface::new(surface, namespace), output, seat));
|
||||
}
|
||||
|
||||
fn new_popup(&mut self, _parent: WlrLayerSurface, popup: PopupSurface) {
|
||||
self.common.shell.unconstrain_popup(&popup);
|
||||
self.common.shell.read().unwrap().unconstrain_popup(&popup);
|
||||
|
||||
if popup.send_configure().is_ok() {
|
||||
self.common
|
||||
.shell
|
||||
.popups
|
||||
.track_popup(PopupKind::from(popup))
|
||||
.unwrap();
|
||||
|
|
@ -51,9 +49,8 @@ impl WlrLayerShellHandler for State {
|
|||
}
|
||||
|
||||
fn layer_destroyed(&mut self, surface: WlrLayerSurface) {
|
||||
let maybe_output = self
|
||||
.common
|
||||
.shell
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let maybe_output = shell
|
||||
.outputs()
|
||||
.find(|o| {
|
||||
let map = layer_map_for_output(o);
|
||||
|
|
@ -72,7 +69,7 @@ impl WlrLayerShellHandler for State {
|
|||
map.unmap_layer(&layer);
|
||||
}
|
||||
|
||||
self.common.shell.workspaces.recalculate();
|
||||
shell.workspaces.recalculate();
|
||||
|
||||
self.backend
|
||||
.schedule_render(&self.common.event_loop_handle, &output);
|
||||
|
|
|
|||
|
|
@ -82,12 +82,16 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
if let Err(err) = self.backend.apply_config_for_output(
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let res = self.backend.apply_config_for_output(
|
||||
output,
|
||||
test_only,
|
||||
&mut self.common.shell,
|
||||
&mut *shell,
|
||||
&self.common.event_loop_handle,
|
||||
) {
|
||||
&mut self.common.workspace_state.update(),
|
||||
&self.common.xdg_activation_state,
|
||||
);
|
||||
if let Err(err) = res {
|
||||
warn!(
|
||||
?err,
|
||||
"Failed to apply config to {}. Resetting",
|
||||
|
|
@ -106,8 +110,10 @@ impl State {
|
|||
if let Err(err) = self.backend.apply_config_for_output(
|
||||
output,
|
||||
false,
|
||||
&mut self.common.shell,
|
||||
&mut *shell,
|
||||
&self.common.event_loop_handle,
|
||||
&mut self.common.workspace_state.update(),
|
||||
&self.common.xdg_activation_state,
|
||||
) {
|
||||
error!(?err, "Failed to reset output config for {}.", output.name(),);
|
||||
}
|
||||
|
|
@ -115,6 +121,9 @@ impl State {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::mem::drop(shell);
|
||||
self.common.refresh();
|
||||
}
|
||||
|
||||
for output in conf
|
||||
|
|
|
|||
|
|
@ -52,8 +52,9 @@ impl ScreencopyHandler for State {
|
|||
.upgrade()
|
||||
.and_then(|output| constraints_for_output(&output, &mut self.backend)),
|
||||
ImageSourceData::Workspace(handle) => {
|
||||
let workspace = self.common.shell.workspaces.space_for_handle(&handle)?;
|
||||
constraints_for_output(workspace.output(), &mut self.backend)
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
let output = shell.workspaces.space_for_handle(&handle)?.output();
|
||||
constraints_for_output(output, &mut self.backend)
|
||||
}
|
||||
ImageSourceData::Toplevel(window) => {
|
||||
constraints_for_toplevel(window, &mut self.backend)
|
||||
|
|
@ -65,6 +66,8 @@ impl ScreencopyHandler for State {
|
|||
let size = if let Some((geometry, _)) = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.cursor_geometry((0.0, 0.0), self.common.clock.now())
|
||||
|
|
@ -98,8 +101,8 @@ impl ScreencopyHandler for State {
|
|||
output.add_session(session);
|
||||
}
|
||||
ImageSourceData::Workspace(handle) => {
|
||||
let Some(workspace) = self.common.shell.workspaces.space_for_handle_mut(&handle)
|
||||
else {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
|
||||
session.stop();
|
||||
return;
|
||||
};
|
||||
|
|
@ -127,7 +130,14 @@ impl ScreencopyHandler for State {
|
|||
}
|
||||
fn new_cursor_session(&mut self, session: CursorSession) {
|
||||
let (pointer_loc, pointer_size, hotspot) = {
|
||||
let seat = self.common.shell.seats.last_active();
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.clone();
|
||||
|
||||
let pointer = seat.get_pointer().unwrap();
|
||||
let pointer_loc = pointer.current_location().to_i32_round().as_global();
|
||||
|
|
@ -183,8 +193,8 @@ impl ScreencopyHandler for State {
|
|||
output.add_cursor_session(session);
|
||||
}
|
||||
ImageSourceData::Workspace(handle) => {
|
||||
let Some(workspace) = self.common.shell.workspaces.space_for_handle_mut(&handle)
|
||||
else {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
|
||||
session.stop();
|
||||
return;
|
||||
};
|
||||
|
|
@ -215,9 +225,10 @@ impl ScreencopyHandler for State {
|
|||
workspace.add_cursor_session(session);
|
||||
}
|
||||
ImageSourceData::Toplevel(mut toplevel) => {
|
||||
if let Some(element) = self.common.shell.element_for_surface(&toplevel) {
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
if let Some(element) = shell.element_for_surface(&toplevel) {
|
||||
if element.has_active_window(&toplevel) {
|
||||
if let Some(workspace) = self.common.shell.space_for(element) {
|
||||
if let Some(workspace) = shell.space_for(element) {
|
||||
if let Some(geometry) = workspace.element_geometry(element) {
|
||||
let mut surface_geo = element.active_window_geometry().as_local();
|
||||
surface_geo.loc += geometry.loc;
|
||||
|
|
@ -268,12 +279,20 @@ impl ScreencopyHandler for State {
|
|||
return;
|
||||
}
|
||||
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.clone();
|
||||
render_cursor_to_buffer(self, &session, frame, &seat);
|
||||
}
|
||||
|
||||
fn frame_aborted(&mut self, frame: Frame) {
|
||||
for mut output in self.common.shell.outputs().cloned() {
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
for mut output in shell.outputs().cloned() {
|
||||
output.remove_frame(&frame)
|
||||
}
|
||||
}
|
||||
|
|
@ -286,7 +305,13 @@ impl ScreencopyHandler for State {
|
|||
}
|
||||
}
|
||||
ImageSourceData::Workspace(handle) => {
|
||||
if let Some(workspace) = self.common.shell.workspaces.space_for_handle_mut(&handle)
|
||||
if let Some(workspace) = self
|
||||
.common
|
||||
.shell
|
||||
.write()
|
||||
.unwrap()
|
||||
.workspaces
|
||||
.space_for_handle_mut(&handle)
|
||||
{
|
||||
workspace.remove_session(session)
|
||||
}
|
||||
|
|
@ -304,7 +329,13 @@ impl ScreencopyHandler for State {
|
|||
}
|
||||
}
|
||||
ImageSourceData::Workspace(handle) => {
|
||||
if let Some(workspace) = self.common.shell.workspaces.space_for_handle_mut(&handle)
|
||||
if let Some(workspace) = self
|
||||
.common
|
||||
.shell
|
||||
.write()
|
||||
.unwrap()
|
||||
.workspaces
|
||||
.space_for_handle_mut(&handle)
|
||||
{
|
||||
workspace.remove_cursor_session(session)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,18 +189,16 @@ pub fn render_workspace_to_buffer(
|
|||
#[cfg(feature = "debug")]
|
||||
puffin::profile_function!();
|
||||
|
||||
let Some(workspace) = state.common.shell.workspaces.space_for_handle(&handle) else {
|
||||
let shell = state.common.shell.read().unwrap();
|
||||
let Some(workspace) = shell.workspaces.space_for_handle(&handle) else {
|
||||
session.stop();
|
||||
return;
|
||||
};
|
||||
|
||||
let output = workspace.output().clone();
|
||||
let idx = state
|
||||
.common
|
||||
.shell
|
||||
.workspaces
|
||||
.idx_for_handle(&output, &handle)
|
||||
.unwrap();
|
||||
let idx = shell.workspaces.idx_for_handle(&output, &handle).unwrap();
|
||||
std::mem::drop(shell);
|
||||
|
||||
let mode = output
|
||||
.current_mode()
|
||||
.map(|mode| mode.size.to_logical(1).to_buffer(1, Transform::Normal));
|
||||
|
|
@ -286,7 +284,7 @@ pub fn render_workspace_to_buffer(
|
|||
dt,
|
||||
age,
|
||||
additional_damage,
|
||||
&common.shell,
|
||||
&*common.shell.read().unwrap(),
|
||||
&common.config,
|
||||
&common.theme,
|
||||
common.clock.now(),
|
||||
|
|
@ -314,7 +312,7 @@ pub fn render_workspace_to_buffer(
|
|||
dt,
|
||||
age,
|
||||
additional_damage,
|
||||
&common.shell,
|
||||
&*common.shell.read().unwrap(),
|
||||
&common.config,
|
||||
&common.theme,
|
||||
common.clock.now(),
|
||||
|
|
@ -535,21 +533,23 @@ pub fn render_window_to_buffer(
|
|||
.map(Into::<WindowCaptureElement<R>>::into),
|
||||
);
|
||||
|
||||
let seat = common.shell.seats.last_active().clone();
|
||||
if let Some(location) = {
|
||||
if let Some(mapped) = common.shell.element_for_surface(window) {
|
||||
mapped.cursor_position(&seat).and_then(|mut p| {
|
||||
p -= mapped.active_window_offset().to_f64();
|
||||
if p.x < 0. || p.y < 0. {
|
||||
None
|
||||
} else {
|
||||
Some(p)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} {
|
||||
let shell = common.shell.read().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let location = if let Some(mapped) = shell.element_for_surface(window) {
|
||||
mapped.cursor_position(&seat).and_then(|mut p| {
|
||||
p -= mapped.active_window_offset().to_f64();
|
||||
if p.x < 0. || p.y < 0. {
|
||||
None
|
||||
} else {
|
||||
Some(p)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
std::mem::drop(shell);
|
||||
|
||||
if let Some(location) = location {
|
||||
if draw_cursor {
|
||||
elements.extend(
|
||||
cursor::draw_cursor(
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ impl SelectionHandler for State {
|
|||
) {
|
||||
if let Some(xwm) = self
|
||||
.common
|
||||
.shell
|
||||
.xwayland_state
|
||||
.as_mut()
|
||||
.and_then(|xstate| xstate.xwm.as_mut())
|
||||
|
|
@ -45,7 +44,6 @@ impl SelectionHandler for State {
|
|||
) {
|
||||
if let Some(xwm) = self
|
||||
.common
|
||||
.shell
|
||||
.xwayland_state
|
||||
.as_mut()
|
||||
.and_then(|xstate| xstate.xwm.as_mut())
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@ impl SessionLockHandler for State {
|
|||
}
|
||||
|
||||
fn lock(&mut self, locker: SessionLocker) {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
||||
// Reject lock if sesion lock exists and is still valid
|
||||
if let Some(session_lock) = self.common.shell.session_lock.as_ref() {
|
||||
if let Some(session_lock) = shell.session_lock.as_ref() {
|
||||
if self
|
||||
.common
|
||||
.display_handle
|
||||
|
|
@ -32,28 +34,30 @@ impl SessionLockHandler for State {
|
|||
|
||||
let ext_session_lock = locker.ext_session_lock().clone();
|
||||
locker.lock();
|
||||
self.common.shell.session_lock = Some(SessionLock {
|
||||
shell.session_lock = Some(SessionLock {
|
||||
ext_session_lock,
|
||||
surfaces: HashMap::new(),
|
||||
});
|
||||
|
||||
for output in self.common.shell.outputs() {
|
||||
for output in shell.outputs() {
|
||||
self.backend
|
||||
.schedule_render(&self.common.event_loop_handle, &output);
|
||||
}
|
||||
}
|
||||
|
||||
fn unlock(&mut self) {
|
||||
self.common.shell.session_lock = None;
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
shell.session_lock = None;
|
||||
|
||||
for output in self.common.shell.outputs() {
|
||||
for output in shell.outputs() {
|
||||
self.backend
|
||||
.schedule_render(&self.common.event_loop_handle, &output);
|
||||
}
|
||||
}
|
||||
|
||||
fn new_surface(&mut self, lock_surface: LockSurface, wl_output: WlOutput) {
|
||||
if let Some(session_lock) = &mut self.common.shell.session_lock {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(session_lock) = &mut shell.session_lock {
|
||||
if let Some(output) = Output::from_resource(&wl_output) {
|
||||
lock_surface.with_pending_state(|states| {
|
||||
let size = output.geometry().size;
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ impl ToplevelInfoHandler for State {
|
|||
type Window = CosmicSurface;
|
||||
|
||||
fn toplevel_info_state(&self) -> &ToplevelInfoState<State, Self::Window> {
|
||||
&self.common.shell.toplevel_info_state
|
||||
&self.common.toplevel_info_state
|
||||
}
|
||||
fn toplevel_info_state_mut(&mut self) -> &mut ToplevelInfoState<State, Self::Window> {
|
||||
&mut self.common.shell.toplevel_info_state
|
||||
&mut self.common.toplevel_info_state
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,15 +15,15 @@ use crate::{
|
|||
wayland::protocols::{
|
||||
toplevel_info::ToplevelInfoHandler,
|
||||
toplevel_management::{
|
||||
delegate_toplevel_management, ManagementWindow, ToplevelManagementHandler,
|
||||
ToplevelManagementState,
|
||||
delegate_toplevel_management, toplevel_rectangle_for, ManagementWindow,
|
||||
ToplevelManagementHandler, ToplevelManagementState,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
impl ToplevelManagementHandler for State {
|
||||
fn toplevel_management_state(&mut self) -> &mut ToplevelManagementState {
|
||||
&mut self.common.shell.toplevel_management_state
|
||||
&mut self.common.toplevel_management_state
|
||||
}
|
||||
|
||||
fn activate(
|
||||
|
|
@ -33,17 +33,10 @@ impl ToplevelManagementHandler for State {
|
|||
seat: Option<Seat<Self>>,
|
||||
) {
|
||||
self.unminimize(dh, window);
|
||||
for output in self
|
||||
.common
|
||||
.shell
|
||||
.outputs()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.iter()
|
||||
{
|
||||
let maybe = self
|
||||
.common
|
||||
.shell
|
||||
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
for output in shell.outputs().cloned().collect::<Vec<_>>().iter() {
|
||||
let maybe = shell
|
||||
.workspaces
|
||||
.spaces_for_output(output)
|
||||
.enumerate()
|
||||
|
|
@ -53,19 +46,22 @@ impl ToplevelManagementHandler for State {
|
|||
.any(|w| &w == window)
|
||||
});
|
||||
if let Some((idx, workspace)) = maybe {
|
||||
let seat = seat.unwrap_or(self.common.shell.seats.last_active().clone());
|
||||
let seat = seat.unwrap_or(shell.seats.last_active().clone());
|
||||
let mapped = workspace
|
||||
.mapped()
|
||||
.find(|m| m.windows().any(|(w, _)| &w == window))
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
let _ = self.common.shell.activate(
|
||||
let _ = shell.activate(
|
||||
&output,
|
||||
idx as usize,
|
||||
WorkspaceDelta::new_shortcut(),
|
||||
&mut self.common.workspace_state.update(),
|
||||
); // TODO: Move pointer?
|
||||
mapped.focus_window(window);
|
||||
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&mapped.clone().into()), &seat, None);
|
||||
return;
|
||||
}
|
||||
|
|
@ -83,16 +79,12 @@ impl ToplevelManagementHandler for State {
|
|||
workspace: ZcosmicWorkspaceHandleV1,
|
||||
_output: Output,
|
||||
) {
|
||||
let Some(to_handle) = self
|
||||
.common
|
||||
.shell
|
||||
.workspace_state
|
||||
.get_workspace_handle(&workspace)
|
||||
else {
|
||||
let Some(to_handle) = self.common.workspace_state.get_workspace_handle(&workspace) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let from_workspace = self.common.shell.workspaces.spaces().find(|w| {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let from_workspace = shell.workspaces.spaces().find(|w| {
|
||||
w.mapped()
|
||||
.flat_map(|m| m.windows().map(|(s, _)| s))
|
||||
.any(|w| &w == window)
|
||||
|
|
@ -104,15 +96,18 @@ impl ToplevelManagementHandler for State {
|
|||
.unwrap()
|
||||
.clone();
|
||||
let from_handle = from_workspace.handle;
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
if let Some((target, _)) = self.common.shell.move_window(
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res = shell.move_window(
|
||||
Some(&seat),
|
||||
&mapped,
|
||||
&from_handle,
|
||||
&to_handle,
|
||||
false,
|
||||
None,
|
||||
) {
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
if let Some((target, _)) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None);
|
||||
}
|
||||
return;
|
||||
|
|
@ -125,29 +120,19 @@ impl ToplevelManagementHandler for State {
|
|||
window: &<Self as ToplevelInfoHandler>::Window,
|
||||
output: Option<Output>,
|
||||
) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(window).cloned() {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
if let Some(output) = output {
|
||||
let from = self
|
||||
.common
|
||||
.shell
|
||||
.toplevel_management_state
|
||||
.minimize_rectangle(&output, window);
|
||||
let workspace = self.common.shell.workspaces.active_mut(&output);
|
||||
let from = minimize_rectangle(&output, window);
|
||||
let workspace = shell.workspaces.active_mut(&output);
|
||||
workspace.fullscreen_request(window, None, from, &seat);
|
||||
} else if let Some((output, handle)) = self
|
||||
.common
|
||||
.shell
|
||||
} else if let Some((output, handle)) = shell
|
||||
.space_for(&mapped)
|
||||
.map(|workspace| (workspace.output.clone(), workspace.handle.clone()))
|
||||
{
|
||||
let from = self
|
||||
.common
|
||||
.shell
|
||||
.toplevel_management_state
|
||||
.minimize_rectangle(&output, window);
|
||||
self.common
|
||||
.shell
|
||||
let from = minimize_rectangle(&output, window);
|
||||
shell
|
||||
.workspaces
|
||||
.space_for_handle_mut(&handle)
|
||||
.unwrap()
|
||||
|
|
@ -161,20 +146,19 @@ impl ToplevelManagementHandler for State {
|
|||
_dh: &DisplayHandle,
|
||||
window: &<Self as ToplevelInfoHandler>::Window,
|
||||
) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(window).cloned() {
|
||||
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
if let Some((layer, previous_workspace)) = workspace.unfullscreen_request(window) {
|
||||
let old_handle = workspace.handle.clone();
|
||||
let new_workspace_handle = self
|
||||
.common
|
||||
.shell
|
||||
let new_workspace_handle = shell
|
||||
.workspaces
|
||||
.space_for_handle(&previous_workspace)
|
||||
.is_some()
|
||||
.then_some(previous_workspace)
|
||||
.unwrap_or(old_handle); // if the workspace doesn't exist anymore, we can still remap on the right layer
|
||||
|
||||
self.common.shell.remap_unfullscreened_window(
|
||||
shell.remap_unfullscreened_window(
|
||||
mapped,
|
||||
&old_handle,
|
||||
&new_workspace_handle,
|
||||
|
|
@ -186,30 +170,34 @@ impl ToplevelManagementHandler for State {
|
|||
}
|
||||
|
||||
fn maximize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(window).cloned() {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.maximize_request(&mapped, &seat);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_request(&mapped, &seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn unmaximize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(window).cloned() {
|
||||
self.common.shell.unmaximize_request(&mapped);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
shell.unmaximize_request(&mapped);
|
||||
}
|
||||
}
|
||||
|
||||
fn minimize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(window).cloned() {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
if !mapped.is_stack() || &mapped.active_window() == window {
|
||||
self.common.shell.minimize_request(&mapped);
|
||||
shell.minimize_request(&mapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unminimize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
if let Some(mut mapped) = self.common.shell.element_for_surface(window).cloned() {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.unminimize_request(&mapped, &seat);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mut mapped) = shell.element_for_surface(window).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.unminimize_request(&mapped, &seat);
|
||||
if mapped.is_stack() {
|
||||
mapped.stack_ref_mut().unwrap().set_active(window);
|
||||
}
|
||||
|
|
@ -223,43 +211,29 @@ impl ManagementWindow for CosmicSurface {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ToplevelManagementExt {
|
||||
fn minimize_rectangle(
|
||||
&mut self,
|
||||
output: &Output,
|
||||
window: &CosmicSurface,
|
||||
) -> Rectangle<i32, Local>;
|
||||
}
|
||||
|
||||
impl ToplevelManagementExt for ToplevelManagementState {
|
||||
fn minimize_rectangle(
|
||||
&mut self,
|
||||
output: &Output,
|
||||
window: &CosmicSurface,
|
||||
) -> Rectangle<i32, Local> {
|
||||
self.rectangle_for(window)
|
||||
.find_map(|(surface, relative)| {
|
||||
let map = layer_map_for_output(output);
|
||||
let layer = map.layer_for_surface(&surface, WindowSurfaceType::ALL);
|
||||
layer.and_then(|s| map.layer_geometry(s)).map(|local| {
|
||||
Rectangle::from_loc_and_size(
|
||||
Point::from((local.loc.x + relative.loc.x, local.loc.y + relative.loc.y)),
|
||||
relative.size,
|
||||
)
|
||||
})
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let output_size = output.geometry().size;
|
||||
pub fn minimize_rectangle(output: &Output, window: &CosmicSurface) -> Rectangle<i32, Local> {
|
||||
toplevel_rectangle_for(window)
|
||||
.find_map(|(surface, relative)| {
|
||||
let map = layer_map_for_output(output);
|
||||
let layer = map.layer_for_surface(&surface, WindowSurfaceType::ALL);
|
||||
layer.and_then(|s| map.layer_geometry(s)).map(|local| {
|
||||
Rectangle::from_loc_and_size(
|
||||
Point::from((
|
||||
(output_size.w / 2) - 100,
|
||||
output_size.h - (output_size.h / 3) - 50,
|
||||
)),
|
||||
Size::from((200, 100)),
|
||||
Point::from((local.loc.x + relative.loc.x, local.loc.y + relative.loc.y)),
|
||||
relative.size,
|
||||
)
|
||||
})
|
||||
.as_local()
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let output_size = output.geometry().size;
|
||||
Rectangle::from_loc_and_size(
|
||||
Point::from((
|
||||
(output_size.w / 2) - 100,
|
||||
output_size.h - (output_size.h / 3) - 50,
|
||||
)),
|
||||
Size::from((200, 100)),
|
||||
)
|
||||
})
|
||||
.as_local()
|
||||
}
|
||||
|
||||
delegate_toplevel_management!(State);
|
||||
|
|
|
|||
|
|
@ -21,17 +21,18 @@ impl WorkspaceClientHandler for ClientState {
|
|||
impl WorkspaceHandler for State {
|
||||
type Client = ClientState;
|
||||
fn workspace_state(&self) -> &WorkspaceState<Self> {
|
||||
&self.common.shell.workspace_state
|
||||
&self.common.workspace_state
|
||||
}
|
||||
fn workspace_state_mut(&mut self) -> &mut WorkspaceState<Self> {
|
||||
&mut self.common.shell.workspace_state
|
||||
&mut self.common.workspace_state
|
||||
}
|
||||
|
||||
fn commit_requests(&mut self, _dh: &DisplayHandle, requests: Vec<Request>) {
|
||||
for request in requests.into_iter() {
|
||||
match request {
|
||||
Request::Activate(handle) => {
|
||||
let maybe = self.common.shell.workspaces.iter().find_map(|(o, set)| {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let maybe = shell.workspaces.iter().find_map(|(o, set)| {
|
||||
set.workspaces
|
||||
.iter()
|
||||
.position(|w| w.handle == handle)
|
||||
|
|
@ -39,22 +40,20 @@ impl WorkspaceHandler for State {
|
|||
});
|
||||
|
||||
if let Some((output, idx)) = maybe {
|
||||
let _ = self.common.shell.activate(
|
||||
let _ = shell.activate(
|
||||
&output,
|
||||
idx,
|
||||
WorkspaceDelta::new_shortcut(),
|
||||
); // TODO: move cursor?
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
// TODO: move cursor?
|
||||
}
|
||||
}
|
||||
Request::SetTilingState { workspace, state } => {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
if let Some(workspace) = self
|
||||
.common
|
||||
.shell
|
||||
.workspaces
|
||||
.space_for_handle_mut(&workspace)
|
||||
{
|
||||
let mut guard = self.common.shell.workspace_state.update();
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(workspace) = shell.workspaces.space_for_handle_mut(&workspace) {
|
||||
let mut guard = self.common.workspace_state.update();
|
||||
workspace.set_tiling(
|
||||
match state.into_result() {
|
||||
Ok(TilingState::FloatingOnly) => false,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
use crate::{shell::ActivationKey, state::ClientState, utils::prelude::*};
|
||||
use crate::{state::State, wayland::protocols::workspace::WorkspaceHandle};
|
||||
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::State as WState;
|
||||
use smithay::{
|
||||
delegate_xdg_activation,
|
||||
input::Seat,
|
||||
|
|
@ -8,9 +11,6 @@ use smithay::{
|
|||
};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{shell::ActivationKey, state::ClientState, utils::prelude::*};
|
||||
use crate::{state::State, wayland::protocols::workspace::WorkspaceHandle};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ActivationContext {
|
||||
UrgentOnly,
|
||||
|
|
@ -19,7 +19,7 @@ pub enum ActivationContext {
|
|||
|
||||
impl XdgActivationHandler for State {
|
||||
fn activation_state(&mut self) -> &mut XdgActivationState {
|
||||
&mut self.common.shell.xdg_activation_state
|
||||
&mut self.common.xdg_activation_state
|
||||
}
|
||||
|
||||
fn token_created(&mut self, token: XdgActivationToken, data: XdgActivationTokenData) -> bool {
|
||||
|
|
@ -41,7 +41,8 @@ impl XdgActivationHandler for State {
|
|||
{
|
||||
if let Some(seat) = data.serial.and_then(|(_, seat)| Seat::from_resource(&seat)) {
|
||||
let output = seat.active_output();
|
||||
let workspace = self.common.shell.active_space_mut(&output);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let workspace = shell.active_space_mut(&output);
|
||||
workspace.pending_tokens.insert(token.clone());
|
||||
let handle = workspace.handle;
|
||||
data.user_data
|
||||
|
|
@ -84,7 +85,8 @@ impl XdgActivationHandler for State {
|
|||
|
||||
if valid {
|
||||
let output = seat.active_output();
|
||||
let workspace = self.common.shell.active_space_mut(&output);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let workspace = shell.active_space_mut(&output);
|
||||
workspace.pending_tokens.insert(token.clone());
|
||||
let handle = workspace.handle;
|
||||
data.user_data
|
||||
|
|
@ -105,24 +107,24 @@ impl XdgActivationHandler for State {
|
|||
surface: WlSurface,
|
||||
) {
|
||||
if let Some(context) = token_data.user_data.get::<ActivationContext>() {
|
||||
if let Some(element) = self.common.shell.element_for_surface(&surface).cloned() {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(element) = shell.element_for_surface(&surface).cloned() {
|
||||
match context {
|
||||
ActivationContext::UrgentOnly => {
|
||||
if let Some((workspace, _output)) =
|
||||
self.common.shell.workspace_for_surface(&surface)
|
||||
{
|
||||
self.common.shell.set_urgent(&workspace);
|
||||
if let Some((workspace, _output)) = shell.workspace_for_surface(&surface) {
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&workspace, WState::Urgent);
|
||||
}
|
||||
}
|
||||
ActivationContext::Workspace(workspace) => {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let current_output = seat.active_output();
|
||||
|
||||
if element.is_minimized() {
|
||||
self.common.shell.unminimize_request(&element, &seat);
|
||||
shell.unminimize_request(&element, &seat);
|
||||
}
|
||||
|
||||
let current_workspace = self.common.shell.active_space_mut(¤t_output);
|
||||
let current_workspace = shell.active_space_mut(¤t_output);
|
||||
|
||||
let in_current_workspace = current_workspace
|
||||
.floating_layer
|
||||
|
|
@ -152,21 +154,19 @@ impl XdgActivationHandler for State {
|
|||
|
||||
if workspace == ¤t_workspace.handle || in_current_workspace {
|
||||
let target = element.into();
|
||||
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None);
|
||||
} else if let Some(w) = self
|
||||
.common
|
||||
.shell
|
||||
.space_for(&element)
|
||||
.map(|w| w.handle.clone())
|
||||
} else if let Some(w) = shell.space_for(&element).map(|w| w.handle.clone())
|
||||
{
|
||||
self.common.shell.append_focus_stack(&element, &seat);
|
||||
self.common.shell.set_urgent(&w);
|
||||
shell.append_focus_stack(&element, &seat);
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&w, WState::Urgent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.common
|
||||
.shell
|
||||
shell
|
||||
.pending_activations
|
||||
.insert(ActivationKey::Wayland(surface), context.clone());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use crate::{
|
||||
shell::{element::CosmicWindow, grabs::ReleaseMode, CosmicMapped, CosmicSurface, ManagedLayer},
|
||||
utils::prelude::*,
|
||||
wayland::protocols::toplevel_info::{toplevel_enter_output, toplevel_enter_workspace},
|
||||
};
|
||||
use smithay::{
|
||||
delegate_xdg_shell,
|
||||
|
|
@ -29,7 +30,7 @@ use smithay::{
|
|||
use std::cell::Cell;
|
||||
use tracing::warn;
|
||||
|
||||
use super::{compositor::client_compositor_state, toplevel_management::ToplevelManagementExt};
|
||||
use super::{compositor::client_compositor_state, toplevel_management::minimize_rectangle};
|
||||
|
||||
pub mod popup;
|
||||
|
||||
|
|
@ -37,13 +38,14 @@ pub type PopupGrabData = Cell<Option<PopupGrab<State>>>;
|
|||
|
||||
impl XdgShellHandler for State {
|
||||
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
|
||||
&mut self.common.shell.xdg_shell_state
|
||||
&mut self.common.xdg_shell_state
|
||||
}
|
||||
|
||||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let window = CosmicSurface::from(surface);
|
||||
self.common.shell.pending_windows.push((window, seat, None));
|
||||
shell.pending_windows.push((window, seat, None));
|
||||
// We will position the window after the first commit, when we know its size hints
|
||||
}
|
||||
|
||||
|
|
@ -55,11 +57,14 @@ impl XdgShellHandler for State {
|
|||
|
||||
if surface.get_parent_surface().is_some() {
|
||||
// let other shells deal with their popups
|
||||
self.common.shell.unconstrain_popup(&surface);
|
||||
self.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.unconstrain_popup(&surface);
|
||||
|
||||
if surface.send_configure().is_ok() {
|
||||
self.common
|
||||
.shell
|
||||
.popups
|
||||
.track_popup(PopupKind::from(surface))
|
||||
.unwrap();
|
||||
|
|
@ -70,16 +75,18 @@ impl XdgShellHandler for State {
|
|||
fn grab(&mut self, surface: PopupSurface, seat: WlSeat, serial: Serial) {
|
||||
let seat = Seat::from_resource(&seat).unwrap();
|
||||
let kind = PopupKind::Xdg(surface);
|
||||
if let Some(root) = find_popup_root_surface(&kind)
|
||||
.ok()
|
||||
.and_then(|root| self.common.shell.element_for_surface(&root))
|
||||
{
|
||||
let target = root.clone().into();
|
||||
let ret = self
|
||||
.common
|
||||
let maybe_root = find_popup_root_surface(&kind).ok().and_then(|root| {
|
||||
self.common
|
||||
.shell
|
||||
.popups
|
||||
.grab_popup(target, kind, &seat, serial);
|
||||
.read()
|
||||
.unwrap()
|
||||
.element_for_surface(&root)
|
||||
.cloned()
|
||||
});
|
||||
|
||||
if let Some(root) = maybe_root {
|
||||
let target = root.into();
|
||||
let ret = self.common.popups.grab_popup(target, kind, &seat, serial);
|
||||
|
||||
if let Ok(mut grab) = ret {
|
||||
if let Some(keyboard) = seat.get_keyboard() {
|
||||
|
|
@ -128,7 +135,11 @@ impl XdgShellHandler for State {
|
|||
state.positioner = positioner;
|
||||
});
|
||||
|
||||
self.common.shell.unconstrain_popup(&surface);
|
||||
self.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.unconstrain_popup(&surface);
|
||||
surface.send_repositioned(token);
|
||||
if let Err(err) = surface.send_configure() {
|
||||
warn!(
|
||||
|
|
@ -140,14 +151,26 @@ impl XdgShellHandler for State {
|
|||
|
||||
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
|
||||
let seat = Seat::from_resource(&seat).unwrap();
|
||||
Shell::move_request(
|
||||
self,
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some((grab, focus)) = shell.move_request(
|
||||
surface.wl_surface(),
|
||||
&seat,
|
||||
serial,
|
||||
ReleaseMode::NoMouseButtons,
|
||||
false,
|
||||
)
|
||||
&self.common.config,
|
||||
&self.common.event_loop_handle,
|
||||
&self.common.xdg_activation_state,
|
||||
) {
|
||||
std::mem::drop(shell);
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(self, grab, serial);
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(self, grab, serial, focus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resize_request(
|
||||
|
|
@ -158,70 +181,60 @@ impl XdgShellHandler for State {
|
|||
edges: xdg_toplevel::ResizeEdge,
|
||||
) {
|
||||
let seat = Seat::from_resource(&seat).unwrap();
|
||||
Shell::resize_request(self, surface.wl_surface(), &seat, serial, edges.into())
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some((grab, focus)) =
|
||||
shell.resize_request(surface.wl_surface(), &seat, serial, edges.into())
|
||||
{
|
||||
std::mem::drop(shell);
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch().unwrap().set_grab(self, grab, serial)
|
||||
} else {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(self, grab, serial, focus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn minimize_request(&mut self, surface: ToplevelSurface) {
|
||||
if let Some(mapped) = self
|
||||
.common
|
||||
.shell
|
||||
.element_for_surface(surface.wl_surface())
|
||||
.cloned()
|
||||
{
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
if !mapped.is_stack()
|
||||
|| mapped.active_window().wl_surface().as_ref() == Some(surface.wl_surface())
|
||||
{
|
||||
self.common.shell.minimize_request(&mapped)
|
||||
shell.minimize_request(&mapped)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn maximize_request(&mut self, surface: ToplevelSurface) {
|
||||
if let Some(mapped) = self
|
||||
.common
|
||||
.shell
|
||||
.element_for_surface(surface.wl_surface())
|
||||
.cloned()
|
||||
{
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.maximize_request(&mapped, &seat)
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_request(&mapped, &seat)
|
||||
}
|
||||
}
|
||||
|
||||
fn unmaximize_request(&mut self, surface: ToplevelSurface) {
|
||||
if let Some(mapped) = self
|
||||
.common
|
||||
.shell
|
||||
.element_for_surface(surface.wl_surface())
|
||||
.cloned()
|
||||
{
|
||||
self.common.shell.unmaximize_request(&mapped);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
shell.unmaximize_request(&mapped);
|
||||
}
|
||||
}
|
||||
|
||||
fn fullscreen_request(&mut self, surface: ToplevelSurface, output: Option<WlOutput>) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let active_output = seat.active_output();
|
||||
let output = output
|
||||
.as_ref()
|
||||
.and_then(Output::from_resource)
|
||||
.unwrap_or_else(|| active_output.clone());
|
||||
|
||||
if let Some(mapped) = self
|
||||
.common
|
||||
.shell
|
||||
.element_for_surface(surface.wl_surface())
|
||||
.cloned()
|
||||
{
|
||||
let from = self
|
||||
.common
|
||||
.shell
|
||||
.toplevel_management_state
|
||||
.minimize_rectangle(&output, &mapped.active_window());
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
let from = minimize_rectangle(&output, &mapped.active_window());
|
||||
|
||||
if let Some(set) = self
|
||||
.common
|
||||
.shell
|
||||
if let Some(set) = shell
|
||||
.workspaces
|
||||
.sets
|
||||
.values_mut()
|
||||
|
|
@ -248,19 +261,13 @@ impl XdgShellHandler for State {
|
|||
mapped
|
||||
};
|
||||
|
||||
let workspace_handle = self.common.shell.active_space(&output).handle.clone();
|
||||
let workspace_handle = shell.active_space(&output).handle.clone();
|
||||
for (window, _) in mapped.windows() {
|
||||
self.common
|
||||
.shell
|
||||
.toplevel_info_state
|
||||
.toplevel_enter_output(&window, &output);
|
||||
self.common
|
||||
.shell
|
||||
.toplevel_info_state
|
||||
.toplevel_enter_workspace(&window, &workspace_handle);
|
||||
toplevel_enter_output(&window, &output);
|
||||
toplevel_enter_workspace(&window, &workspace_handle);
|
||||
}
|
||||
|
||||
let workspace = self.common.shell.active_space_mut(&output);
|
||||
let workspace = shell.active_space_mut(&output);
|
||||
workspace.floating_layer.map(mapped.clone(), None);
|
||||
|
||||
workspace.fullscreen_request(
|
||||
|
|
@ -269,7 +276,7 @@ impl XdgShellHandler for State {
|
|||
from,
|
||||
&seat,
|
||||
);
|
||||
} else if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
|
||||
} else if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
if workspace.output != output {
|
||||
let (mapped, layer) = if mapped
|
||||
.stack_ref()
|
||||
|
|
@ -300,19 +307,13 @@ impl XdgShellHandler for State {
|
|||
};
|
||||
let handle = workspace.handle.clone();
|
||||
|
||||
let workspace_handle = self.common.shell.active_space(&output).handle.clone();
|
||||
let workspace_handle = shell.active_space(&output).handle.clone();
|
||||
for (window, _) in mapped.windows() {
|
||||
self.common
|
||||
.shell
|
||||
.toplevel_info_state
|
||||
.toplevel_enter_output(&window, &output);
|
||||
self.common
|
||||
.shell
|
||||
.toplevel_info_state
|
||||
.toplevel_enter_workspace(&window, &workspace_handle);
|
||||
toplevel_enter_output(&window, &output);
|
||||
toplevel_enter_workspace(&window, &workspace_handle);
|
||||
}
|
||||
|
||||
let workspace = self.common.shell.active_space_mut(&output);
|
||||
let workspace = shell.active_space_mut(&output);
|
||||
workspace.floating_layer.map(mapped.clone(), None);
|
||||
|
||||
workspace.fullscreen_request(
|
||||
|
|
@ -330,9 +331,7 @@ impl XdgShellHandler for State {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(o) = self
|
||||
.common
|
||||
.shell
|
||||
if let Some(o) = shell
|
||||
.pending_windows
|
||||
.iter_mut()
|
||||
.find(|(s, _, _)| s.wl_surface().as_ref() == Some(surface.wl_surface()))
|
||||
|
|
@ -344,29 +343,23 @@ impl XdgShellHandler for State {
|
|||
}
|
||||
|
||||
fn unfullscreen_request(&mut self, surface: ToplevelSurface) {
|
||||
if let Some(mapped) = self
|
||||
.common
|
||||
.shell
|
||||
.element_for_surface(surface.wl_surface())
|
||||
.cloned()
|
||||
{
|
||||
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
let (window, _) = mapped
|
||||
.windows()
|
||||
.find(|(w, _)| w.wl_surface().as_ref() == Some(surface.wl_surface()))
|
||||
.unwrap();
|
||||
if let Some((layer, previous_workspace)) = workspace.unfullscreen_request(&window) {
|
||||
let old_handle = workspace.handle.clone();
|
||||
let new_workspace_handle = self
|
||||
.common
|
||||
.shell
|
||||
let new_workspace_handle = shell
|
||||
.workspaces
|
||||
.space_for_handle(&previous_workspace)
|
||||
.is_some()
|
||||
.then_some(previous_workspace)
|
||||
.unwrap_or(old_handle); // if the workspace doesn't exist anymore, we can still remap on the right layer
|
||||
|
||||
self.common.shell.remap_unfullscreened_window(
|
||||
shell.remap_unfullscreened_window(
|
||||
mapped,
|
||||
&old_handle,
|
||||
&new_workspace_handle,
|
||||
|
|
@ -378,20 +371,26 @@ impl XdgShellHandler for State {
|
|||
}
|
||||
|
||||
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.unmap_surface(surface.wl_surface(), &seat);
|
||||
let (output, clients) = {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.unmap_surface(
|
||||
surface.wl_surface(),
|
||||
&seat,
|
||||
&mut self.common.toplevel_info_state,
|
||||
);
|
||||
|
||||
let output = self
|
||||
.common
|
||||
.shell
|
||||
.visible_output_for_surface(surface.wl_surface())
|
||||
.cloned();
|
||||
if let Some(output) = output.as_ref() {
|
||||
self.common.shell.refresh_active_space(output);
|
||||
}
|
||||
let output = shell
|
||||
.visible_output_for_surface(surface.wl_surface())
|
||||
.cloned();
|
||||
if let Some(output) = output.as_ref() {
|
||||
shell.refresh_active_space(output, &self.common.xdg_activation_state);
|
||||
}
|
||||
|
||||
// animations might be unblocked now
|
||||
(output, shell.update_animations())
|
||||
};
|
||||
|
||||
// animations might be unblocked now
|
||||
let clients = self.common.shell.update_animations();
|
||||
{
|
||||
let dh = self.common.display_handle.clone();
|
||||
for client in clients.values() {
|
||||
|
|
@ -418,7 +417,23 @@ impl XdgShellHandler for State {
|
|||
})
|
||||
.unwrap_or_default()
|
||||
.loc;
|
||||
Shell::menu_request(self, surface.wl_surface(), &seat, serial, location, false)
|
||||
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
let res = shell.menu_request(
|
||||
surface.wl_surface(),
|
||||
&seat,
|
||||
serial,
|
||||
location,
|
||||
false,
|
||||
&self.common.config,
|
||||
&self.common.event_loop_handle,
|
||||
);
|
||||
if let Some((grab, focus)) = res {
|
||||
std::mem::drop(shell);
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(self, grab, serial, focus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@ impl XWaylandKeyboardGrabHandler for State {
|
|||
let element = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.workspaces
|
||||
.spaces()
|
||||
.find_map(|x| x.element_for_surface(surface))?;
|
||||
Some(KeyboardFocusTarget::Element(element.clone()))
|
||||
.find_map(|x| x.element_for_surface(surface).cloned())?;
|
||||
Some(KeyboardFocusTarget::Element(element))
|
||||
}
|
||||
}
|
||||
delegate_xwayland_keyboard_grab!(State);
|
||||
|
|
|
|||
|
|
@ -185,6 +185,30 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_enter_output(toplevel: &impl Window, output: &Output) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().outputs.push(output.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_leave_output(toplevel: &impl Window, output: &Output) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().outputs.retain(|o| o != output);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_enter_workspace(toplevel: &impl Window, workspace: &WorkspaceHandle) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().workspaces.push(workspace.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_leave_workspace(toplevel: &impl Window, workspace: &WorkspaceHandle) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().workspaces.retain(|w| w != workspace);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D, W> ToplevelInfoState<D, W>
|
||||
where
|
||||
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
||||
|
|
@ -223,30 +247,6 @@ where
|
|||
self.toplevels.push(toplevel.clone());
|
||||
}
|
||||
|
||||
pub fn toplevel_enter_output(&mut self, toplevel: &W, output: &Output) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().outputs.push(output.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_leave_output(&mut self, toplevel: &W, output: &Output) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().outputs.retain(|o| o != output);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_enter_workspace(&mut self, toplevel: &W, workspace: &WorkspaceHandle) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().workspaces.push(workspace.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_leave_workspace(&mut self, toplevel: &W, workspace: &WorkspaceHandle) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
state.lock().unwrap().workspaces.retain(|w| w != workspace);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_toplevel(&mut self, toplevel: &W) {
|
||||
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
let mut state_inner = state.lock().unwrap();
|
||||
|
|
|
|||
|
|
@ -71,6 +71,29 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toplevel_rectangle_for(
|
||||
window: &impl ManagementWindow,
|
||||
) -> impl Iterator<Item = (WlSurface, Rectangle<i32, Logical>)> {
|
||||
if let Some(state) = window.user_data().get::<ToplevelState>() {
|
||||
let mut state = state.lock().unwrap();
|
||||
state
|
||||
.rectangles
|
||||
.retain(|(surface, _)| surface.upgrade().is_ok());
|
||||
Some(
|
||||
state
|
||||
.rectangles
|
||||
.iter()
|
||||
.map(|(surface, rect)| (surface.upgrade().unwrap(), *rect))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
} else {
|
||||
None.into_iter().flatten()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ToplevelManagerGlobalData {
|
||||
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
||||
}
|
||||
|
|
@ -102,30 +125,6 @@ impl ToplevelManagementState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn rectangle_for(
|
||||
&mut self,
|
||||
window: &impl ManagementWindow,
|
||||
) -> impl Iterator<Item = (WlSurface, Rectangle<i32, Logical>)> {
|
||||
if let Some(state) = window.user_data().get::<ToplevelState>() {
|
||||
let mut state = state.lock().unwrap();
|
||||
state
|
||||
.rectangles
|
||||
.retain(|(surface, _)| surface.upgrade().is_ok());
|
||||
Some(
|
||||
state
|
||||
.rectangles
|
||||
.iter()
|
||||
.map(|(surface, rect)| (surface.upgrade().unwrap(), *rect))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
} else {
|
||||
None.into_iter().flatten()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn global_id(&self) -> GlobalId {
|
||||
self.global.clone()
|
||||
}
|
||||
|
|
|
|||
236
src/xwayland.rs
236
src/xwayland.rs
|
|
@ -6,14 +6,14 @@ use crate::{
|
|||
state::State,
|
||||
utils::prelude::*,
|
||||
wayland::handlers::{
|
||||
toplevel_management::ToplevelManagementExt, xdg_activation::ActivationContext,
|
||||
toplevel_management::minimize_rectangle, xdg_activation::ActivationContext,
|
||||
},
|
||||
};
|
||||
use smithay::{
|
||||
backend::drm::DrmNode,
|
||||
desktop::space::SpaceElement,
|
||||
reexports::x11rb::protocol::xproto::Window as X11Window,
|
||||
utils::{Logical, Point, Rectangle, Size},
|
||||
utils::{Logical, Point, Rectangle, Size, SERIAL_COUNTER},
|
||||
wayland::{
|
||||
selection::{
|
||||
data_device::{
|
||||
|
|
@ -45,7 +45,7 @@ pub struct XWaylandState {
|
|||
|
||||
impl State {
|
||||
pub fn launch_xwayland(&mut self, render_node: Option<DrmNode>) {
|
||||
if self.common.shell.xwayland_state.is_some() {
|
||||
if self.common.xwayland_state.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -89,11 +89,11 @@ impl State {
|
|||
);
|
||||
}
|
||||
|
||||
let xwayland_state = data.common.shell.xwayland_state.as_mut().unwrap();
|
||||
let xwayland_state = data.common.xwayland_state.as_mut().unwrap();
|
||||
xwayland_state.xwm = Some(wm);
|
||||
}
|
||||
XWaylandEvent::Exited => {
|
||||
if let Some(mut xwayland_state) = data.common.shell.xwayland_state.take() {
|
||||
if let Some(mut xwayland_state) = data.common.xwayland_state.take() {
|
||||
xwayland_state.xwm = None;
|
||||
}
|
||||
}
|
||||
|
|
@ -118,7 +118,7 @@ impl State {
|
|||
},
|
||||
) {
|
||||
Ok(display) => {
|
||||
self.common.shell.xwayland_state = Some(XWaylandState {
|
||||
self.common.xwayland_state = Some(XWaylandState {
|
||||
xwayland,
|
||||
xwm: None,
|
||||
display,
|
||||
|
|
@ -134,7 +134,14 @@ impl State {
|
|||
|
||||
impl Common {
|
||||
fn is_x_focused(&self, xwm: XwmId) -> bool {
|
||||
if let Some(keyboard) = self.shell.seats.last_active().get_keyboard() {
|
||||
if let Some(keyboard) = self
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.get_keyboard()
|
||||
{
|
||||
if let Some(KeyboardFocusTarget::Element(mapped)) = keyboard.current_focus() {
|
||||
if let Some(surface) = mapped.active_window().x11_surface() {
|
||||
return surface.xwm_id().unwrap() == xwm;
|
||||
|
|
@ -146,22 +153,21 @@ impl Common {
|
|||
}
|
||||
|
||||
pub fn update_x11_stacking_order(&mut self) {
|
||||
let active_output = self.shell.seats.last_active().active_output();
|
||||
let shell = self.shell.read().unwrap();
|
||||
let active_output = shell.seats.last_active().active_output();
|
||||
if let Some(xwm) = self
|
||||
.shell
|
||||
.xwayland_state
|
||||
.as_mut()
|
||||
.and_then(|state| state.xwm.as_mut())
|
||||
{
|
||||
// front to back, given that is how the workspace enumerates
|
||||
let order = self
|
||||
.shell
|
||||
let order = shell
|
||||
.workspaces
|
||||
.sets
|
||||
.iter()
|
||||
.filter(|(output, _)| *output == &active_output)
|
||||
.chain(
|
||||
self.shell
|
||||
shell
|
||||
.workspaces
|
||||
.sets
|
||||
.iter()
|
||||
|
|
@ -233,7 +239,6 @@ impl Common {
|
|||
impl XwmHandler for State {
|
||||
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
|
||||
self.common
|
||||
.shell
|
||||
.xwayland_state
|
||||
.as_mut()
|
||||
.and_then(|state| state.xwm.as_mut())
|
||||
|
|
@ -249,112 +254,100 @@ impl XwmHandler for State {
|
|||
warn!(?window, ?err, "Failed to send Xwayland Mapped-Event",);
|
||||
}
|
||||
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let startup_id = window.startup_id();
|
||||
if self.common.shell.element_for_surface(&window).is_some() {
|
||||
if shell.element_for_surface(&window).is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(context) = startup_id
|
||||
.map(XdgActivationToken::from)
|
||||
.and_then(|token| {
|
||||
self.common
|
||||
.shell
|
||||
.xdg_activation_state
|
||||
.data_for_token(&token)
|
||||
})
|
||||
.and_then(|token| self.common.xdg_activation_state.data_for_token(&token))
|
||||
.and_then(|data| data.user_data.get::<ActivationContext>())
|
||||
{
|
||||
self.common.shell.pending_activations.insert(
|
||||
shell.pending_activations.insert(
|
||||
crate::shell::ActivationKey::X11(window.window_id()),
|
||||
context.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
let surface = CosmicSurface::from(window);
|
||||
self.common
|
||||
.shell
|
||||
.pending_windows
|
||||
.push((surface, seat, None));
|
||||
shell.pending_windows.push((surface, seat, None));
|
||||
}
|
||||
|
||||
fn map_window_notify(&mut self, _xwm: XwmId, surface: X11Surface) {
|
||||
if let Some((window, _, _)) = self
|
||||
.common
|
||||
.shell
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some((window, _, _)) = shell
|
||||
.pending_windows
|
||||
.iter()
|
||||
.find(|(window, _, _)| window.x11_surface() == Some(&surface))
|
||||
.cloned()
|
||||
{
|
||||
if !self
|
||||
.common
|
||||
.shell
|
||||
if !shell
|
||||
.pending_activations
|
||||
.contains_key(&crate::shell::ActivationKey::X11(surface.window_id()))
|
||||
{
|
||||
if let Some(startup_id) = window.x11_surface().and_then(|x| x.startup_id()) {
|
||||
if let Some(context) = self
|
||||
.common
|
||||
.shell
|
||||
.xdg_activation_state
|
||||
.data_for_token(&XdgActivationToken::from(startup_id))
|
||||
.and_then(|data| data.user_data.get::<ActivationContext>())
|
||||
{
|
||||
self.common.shell.pending_activations.insert(
|
||||
shell.pending_activations.insert(
|
||||
crate::shell::ActivationKey::X11(surface.window_id()),
|
||||
context.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(target) = self.common.shell.map_window(
|
||||
let res = shell.map_window(
|
||||
&window,
|
||||
&mut self.common.toplevel_info_state,
|
||||
&mut self.common.workspace_state,
|
||||
&self.common.event_loop_handle,
|
||||
&self.common.theme,
|
||||
) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
);
|
||||
if let Some(target) = res {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
if self
|
||||
.common
|
||||
.shell
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if shell
|
||||
.override_redirect_windows
|
||||
.iter()
|
||||
.any(|or| or == &window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
self.common.shell.map_override_redirect(window)
|
||||
shell.map_override_redirect(window)
|
||||
}
|
||||
|
||||
fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if window.is_override_redirect() {
|
||||
self.common
|
||||
.shell
|
||||
.override_redirect_windows
|
||||
.retain(|or| or != &window);
|
||||
shell.override_redirect_windows.retain(|or| or != &window);
|
||||
} else {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.unmap_surface(&window, &seat);
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.unmap_surface(&window, &seat, &mut self.common.toplevel_info_state);
|
||||
}
|
||||
|
||||
let outputs = if let Some(wl_surface) = window.wl_surface() {
|
||||
self.common
|
||||
.shell
|
||||
shell
|
||||
.visible_output_for_surface(&wl_surface)
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
self.common.shell.outputs().cloned().collect::<Vec<_>>()
|
||||
shell.outputs().cloned().collect::<Vec<_>>()
|
||||
};
|
||||
for output in outputs.iter() {
|
||||
self.common.shell.refresh_active_space(output);
|
||||
shell.refresh_active_space(output, &self.common.xdg_activation_state);
|
||||
}
|
||||
|
||||
for output in outputs.into_iter() {
|
||||
|
|
@ -375,17 +368,15 @@ impl XwmHandler for State {
|
|||
) {
|
||||
// We only allow floating X11 windows to resize themselves. Nothing else
|
||||
let mut current_geo = window.geometry();
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(&window) {
|
||||
let is_floating = self
|
||||
.common
|
||||
.shell
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
|
||||
if let Some(mapped) = shell.element_for_surface(&window) {
|
||||
let is_floating = shell
|
||||
.workspaces
|
||||
.sets
|
||||
.values()
|
||||
.any(|set| set.sticky_layer.mapped().any(|m| m == mapped))
|
||||
|| self
|
||||
.common
|
||||
.shell
|
||||
|| shell
|
||||
.space_for(&mapped)
|
||||
.filter(|space| space.is_floating(mapped))
|
||||
.is_some();
|
||||
|
|
@ -430,8 +421,9 @@ impl XwmHandler for State {
|
|||
above: Option<X11Window>,
|
||||
) {
|
||||
if window.is_override_redirect() {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(id) = above {
|
||||
let or_windows = &mut self.common.shell.override_redirect_windows;
|
||||
let or_windows = &mut shell.override_redirect_windows;
|
||||
if let Some(own_pos) = or_windows.iter().position(|or| or == &window) {
|
||||
let compare_pos = or_windows
|
||||
.iter()
|
||||
|
|
@ -445,7 +437,7 @@ impl XwmHandler for State {
|
|||
}
|
||||
|
||||
let geo = window.geometry().as_global();
|
||||
for (output, overlap) in self.common.shell.outputs().cloned().map(|o| {
|
||||
for (output, overlap) in shell.outputs().cloned().map(|o| {
|
||||
let intersection = o.geometry().intersection(geo);
|
||||
(o, intersection)
|
||||
}) {
|
||||
|
|
@ -466,50 +458,88 @@ impl XwmHandler for State {
|
|||
resize_edge: smithay::xwayland::xwm::ResizeEdge,
|
||||
) {
|
||||
if let Some(wl_surface) = window.wl_surface() {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
Shell::resize_request(self, &wl_surface, &seat, None, resize_edge.into())
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some((grab, focus)) =
|
||||
shell.resize_request(&wl_surface, &seat, None, resize_edge.into())
|
||||
{
|
||||
std::mem::drop(shell);
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch()
|
||||
.unwrap()
|
||||
.set_grab(self, grab, SERIAL_COUNTER.next_serial())
|
||||
} else {
|
||||
seat.get_pointer().unwrap().set_grab(
|
||||
self,
|
||||
grab,
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
focus,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, _button: u32) {
|
||||
if let Some(wl_surface) = window.wl_surface() {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
Shell::move_request(
|
||||
self,
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some((grab, focus)) = shell.move_request(
|
||||
&wl_surface,
|
||||
&seat,
|
||||
None,
|
||||
ReleaseMode::NoMouseButtons,
|
||||
false,
|
||||
)
|
||||
&self.common.config,
|
||||
&self.common.event_loop_handle,
|
||||
&self.common.xdg_activation_state,
|
||||
) {
|
||||
std::mem::drop(shell);
|
||||
if grab.is_touch_grab() {
|
||||
seat.get_touch()
|
||||
.unwrap()
|
||||
.set_grab(self, grab, SERIAL_COUNTER.next_serial())
|
||||
} else {
|
||||
seat.get_pointer().unwrap().set_grab(
|
||||
self,
|
||||
grab,
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
focus,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(&window).cloned() {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.maximize_request(&mapped, &seat);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_request(&mapped, &seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(&window).cloned() {
|
||||
self.common.shell.unmaximize_request(&mapped);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||
shell.unmaximize_request(&mapped);
|
||||
}
|
||||
}
|
||||
|
||||
fn minimize_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(&window).cloned() {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||
if !mapped.is_stack() || mapped.active_window().is_window(&window) {
|
||||
self.common.shell.minimize_request(&mapped);
|
||||
shell.minimize_request(&mapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unminimize_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
if let Some(mut mapped) = self.common.shell.element_for_surface(&window).cloned() {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
self.common.shell.unminimize_request(&mapped, &seat);
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mut mapped) = shell.element_for_surface(&window).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.unminimize_request(&mapped, &seat);
|
||||
if mapped.is_stack() {
|
||||
let maybe_surface = mapped.windows().find(|(w, _)| w.is_window(&window));
|
||||
if let Some((surface, _)) = maybe_surface {
|
||||
|
|
@ -520,11 +550,10 @@ impl XwmHandler for State {
|
|||
}
|
||||
|
||||
fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
let seat = self.common.shell.seats.last_active().clone();
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(&window).cloned() {
|
||||
if let Some((output, handle)) = self
|
||||
.common
|
||||
.shell
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||
if let Some((output, handle)) = shell
|
||||
.space_for(&mapped)
|
||||
.map(|workspace| (workspace.output.clone(), workspace.handle.clone()))
|
||||
{
|
||||
|
|
@ -532,13 +561,8 @@ impl XwmHandler for State {
|
|||
.windows()
|
||||
.find(|(w, _)| w.x11_surface() == Some(&window))
|
||||
{
|
||||
let from = self
|
||||
.common
|
||||
.shell
|
||||
.toplevel_management_state
|
||||
.minimize_rectangle(&output, &surface);
|
||||
self.common
|
||||
.shell
|
||||
let from = minimize_rectangle(&output, &surface);
|
||||
shell
|
||||
.workspaces
|
||||
.space_for_handle_mut(&handle)
|
||||
.unwrap()
|
||||
|
|
@ -547,9 +571,7 @@ impl XwmHandler for State {
|
|||
}
|
||||
} else {
|
||||
let output = seat.active_output();
|
||||
if let Some(o) = self
|
||||
.common
|
||||
.shell
|
||||
if let Some(o) = shell
|
||||
.pending_windows
|
||||
.iter_mut()
|
||||
.find(|(s, _, _)| s.x11_surface() == Some(&window))
|
||||
|
|
@ -561,8 +583,9 @@ impl XwmHandler for State {
|
|||
}
|
||||
|
||||
fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
if let Some(mapped) = self.common.shell.element_for_surface(&window).cloned() {
|
||||
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||
if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
let (window, _) = mapped
|
||||
.windows()
|
||||
.find(|(w, _)| w.x11_surface() == Some(&window))
|
||||
|
|
@ -580,10 +603,17 @@ impl XwmHandler for State {
|
|||
mime_type: String,
|
||||
fd: OwnedFd,
|
||||
) {
|
||||
let seat = self.common.shell.seats.last_active();
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.clone();
|
||||
match selection {
|
||||
SelectionTarget::Clipboard => {
|
||||
if let Err(err) = request_data_device_client_selection(seat, mime_type, fd) {
|
||||
if let Err(err) = request_data_device_client_selection(&seat, mime_type, fd) {
|
||||
error!(
|
||||
?err,
|
||||
"Failed to request current wayland clipboard for Xwayland.",
|
||||
|
|
@ -591,7 +621,7 @@ impl XwmHandler for State {
|
|||
}
|
||||
}
|
||||
SelectionTarget::Primary => {
|
||||
if let Err(err) = request_primary_client_selection(seat, mime_type, fd) {
|
||||
if let Err(err) = request_primary_client_selection(&seat, mime_type, fd) {
|
||||
error!(
|
||||
?err,
|
||||
"Failed to request current wayland primary selection for Xwayland.",
|
||||
|
|
@ -609,7 +639,14 @@ impl XwmHandler for State {
|
|||
trace!(?selection, ?mime_types, "Got Selection from Xwayland",);
|
||||
|
||||
if self.common.is_x_focused(xwm) {
|
||||
let seat = self.common.shell.seats.last_active();
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.unwrap()
|
||||
.seats
|
||||
.last_active()
|
||||
.clone();
|
||||
match selection {
|
||||
SelectionTarget::Clipboard => {
|
||||
set_data_device_selection(&self.common.display_handle, &seat, mime_types, xwm)
|
||||
|
|
@ -622,7 +659,8 @@ impl XwmHandler for State {
|
|||
}
|
||||
|
||||
fn cleared_selection(&mut self, xwm: XwmId, selection: SelectionTarget) {
|
||||
for seat in self.common.shell.seats.iter() {
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
for seat in shell.seats.iter() {
|
||||
match selection {
|
||||
SelectionTarget::Clipboard => {
|
||||
if current_data_device_selection_userdata(seat).as_deref() == Some(&xwm) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue