@@ -31,7 +31,7 @@ use crate::{
3131} ;
3232use calloop:: {
3333 timer:: { TimeoutAction , Timer } ,
34- RegistrationToken ,
34+ LoopHandle , RegistrationToken ,
3535} ;
3636use cosmic_comp_config:: { workspace:: WorkspaceLayout , NumlockState } ;
3737use cosmic_settings_config:: shortcuts;
@@ -58,7 +58,8 @@ use smithay::{
5858 } ,
5959 output:: Output ,
6060 reexports:: {
61- input:: Device as InputDevice , wayland_server:: protocol:: wl_shm:: Format as ShmFormat ,
61+ input:: Device as InputDevice ,
62+ wayland_server:: protocol:: { wl_shm:: Format as ShmFormat , wl_surface:: WlSurface } ,
6263 } ,
6364 utils:: { Point , Rectangle , Serial , SERIAL_COUNTER } ,
6465 wayland:: {
@@ -693,6 +694,66 @@ impl State {
693694 }
694695 }
695696
697+ fn window_menu (
698+ seat : Seat < State > ,
699+ evlh : & LoopHandle < State > ,
700+ surface : WlSurface ,
701+ serial : Serial ,
702+ ) {
703+ evlh. insert_idle ( move |state| {
704+ let shell = state. common . shell . write ( ) . unwrap ( ) ;
705+
706+ let grab = if let Some ( mapped) =
707+ shell. element_for_surface ( & surface) . cloned ( )
708+ {
709+ let position = if let Some ( ( output, set) ) =
710+ shell. workspaces . sets . iter ( ) . find ( |( _, set) | {
711+ set. sticky_layer
712+ . mapped ( )
713+ . any ( |m| m == & mapped)
714+ } ) {
715+ set. sticky_layer
716+ . element_geometry ( & mapped)
717+ . unwrap ( )
718+ . loc
719+ . to_global ( output)
720+ } else if let Some ( workspace) =
721+ shell. space_for ( & mapped)
722+ {
723+ let Some ( elem_geo) =
724+ workspace. element_geometry ( & mapped)
725+ else {
726+ return ;
727+ } ;
728+ elem_geo. loc . to_global ( & workspace. output )
729+ } else {
730+ return ;
731+ } ;
732+ let cursor = seat
733+ . get_pointer ( )
734+ . unwrap ( )
735+ . current_location ( )
736+ . to_i32_round ( ) ;
737+
738+ shell. menu_request (
739+ & surface,
740+ & seat,
741+ serial,
742+ cursor - position. as_logical ( ) ,
743+ false ,
744+ & state. common . config ,
745+ & state. common . event_loop_handle ,
746+ false ,
747+ )
748+ } else {
749+ None
750+ } ;
751+ drop ( shell) ;
752+
753+ dispatch_grab ( grab, seat, serial, state) ;
754+ } ) ;
755+ }
756+
696757 if let Some ( mouse_button) = mouse_button {
697758 match mouse_button {
698759 smithay:: backend:: input:: MouseButton :: Left => {
@@ -719,61 +780,89 @@ impl State {
719780 } ,
720781 ) ;
721782 }
722- smithay:: backend:: input:: MouseButton :: Right => {
783+ smithay:: backend:: input:: MouseButton :: Middle => {
723784 supress_button ( ) ;
724- self . common . event_loop_handle . insert_idle (
725- move |state| {
726- let mut shell =
727- state. common . shell . write ( ) . unwrap ( ) ;
728- let Some ( target_elem) =
729- shell. element_for_surface ( & surface)
730- else {
731- return ;
732- } ;
733- let Some ( geom) =
734- shell. space_for ( target_elem) . and_then (
735- |f| f. element_geometry ( target_elem) ,
736- )
737- else {
738- return ;
739- } ;
740- let geom = geom. to_f64 ( ) ;
741- let center =
742- geom. loc + geom. size . downscale ( 2.0 ) ;
743- let offset = center. to_global ( & output)
744- - global_position;
745- let edge = match (
746- offset. x > 0.0 ,
747- offset. y > 0.0 ,
748- ) {
749- ( true , true ) => ResizeEdge :: TOP_LEFT ,
750- ( false , true ) => ResizeEdge :: TOP_RIGHT ,
751- ( true , false ) => {
752- ResizeEdge :: BOTTOM_LEFT
753- }
754- ( false , false ) => {
755- ResizeEdge :: BOTTOM_RIGHT
756- }
757- } ;
758- let res = shell. resize_request (
759- & surface,
760- & seat_clone,
761- serial,
762- edge,
763- state
764- . common
765- . config
766- . cosmic_conf
767- . edge_snap_threshold ,
768- false ,
769- ) ;
770- drop ( shell) ;
771- dispatch_grab (
772- res, seat_clone, serial, state,
773- ) ;
774- } ,
785+ window_menu (
786+ seat_clone,
787+ & self . common . event_loop_handle ,
788+ surface,
789+ serial,
775790 ) ;
776791 }
792+ smithay:: backend:: input:: MouseButton :: Right => {
793+ supress_button ( ) ;
794+ if seat
795+ . get_keyboard ( )
796+ . unwrap ( )
797+ . modifier_state ( )
798+ . shift
799+ {
800+ window_menu (
801+ seat_clone,
802+ & self . common . event_loop_handle ,
803+ surface,
804+ serial,
805+ ) ;
806+ } else {
807+ self . common . event_loop_handle . insert_idle (
808+ move |state| {
809+ let mut shell =
810+ state. common . shell . write ( ) . unwrap ( ) ;
811+ let Some ( target_elem) =
812+ shell. element_for_surface ( & surface)
813+ else {
814+ return ;
815+ } ;
816+ let Some ( geom) = shell
817+ . space_for ( target_elem)
818+ . and_then ( |f| {
819+ f. element_geometry ( target_elem)
820+ } )
821+ else {
822+ return ;
823+ } ;
824+ let geom = geom. to_f64 ( ) ;
825+ let center =
826+ geom. loc + geom. size . downscale ( 2.0 ) ;
827+ let offset = center. to_global ( & output)
828+ - global_position;
829+ let edge = match (
830+ offset. x > 0.0 ,
831+ offset. y > 0.0 ,
832+ ) {
833+ ( true , true ) => {
834+ ResizeEdge :: TOP_LEFT
835+ }
836+ ( false , true ) => {
837+ ResizeEdge :: TOP_RIGHT
838+ }
839+ ( true , false ) => {
840+ ResizeEdge :: BOTTOM_LEFT
841+ }
842+ ( false , false ) => {
843+ ResizeEdge :: BOTTOM_RIGHT
844+ }
845+ } ;
846+ let res = shell. resize_request (
847+ & surface,
848+ & seat_clone,
849+ serial,
850+ edge,
851+ state
852+ . common
853+ . config
854+ . cosmic_conf
855+ . edge_snap_threshold ,
856+ false ,
857+ ) ;
858+ drop ( shell) ;
859+ dispatch_grab (
860+ res, seat_clone, serial, state,
861+ ) ;
862+ } ,
863+ ) ;
864+ }
865+ }
777866 _ => { }
778867 }
779868 }
@@ -807,8 +896,6 @@ impl State {
807896 } ,
808897 ) ;
809898 ptr. frame ( self ) ;
810- } else if event. state ( ) == ButtonState :: Released {
811- ptr. unset_grab ( self , serial, event. time_msec ( ) )
812899 }
813900 }
814901 InputEvent :: PointerAxis { event, .. } => {
0 commit comments