@@ -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 ;
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:: {
@@ -677,6 +678,66 @@ impl State {
677678 }
678679 }
679680
681+ fn window_menu (
682+ seat : Seat < State > ,
683+ evlh : & LoopHandle < State > ,
684+ surface : WlSurface ,
685+ serial : Serial ,
686+ ) {
687+ evlh. insert_idle ( move |state| {
688+ let shell = state. common . shell . write ( ) . unwrap ( ) ;
689+
690+ let grab = if let Some ( mapped) =
691+ shell. element_for_surface ( & surface) . cloned ( )
692+ {
693+ let position = if let Some ( ( output, set) ) =
694+ shell. workspaces . sets . iter ( ) . find ( |( _, set) | {
695+ set. sticky_layer
696+ . mapped ( )
697+ . any ( |m| m == & mapped)
698+ } ) {
699+ set. sticky_layer
700+ . element_geometry ( & mapped)
701+ . unwrap ( )
702+ . loc
703+ . to_global ( output)
704+ } else if let Some ( workspace) =
705+ shell. space_for ( & mapped)
706+ {
707+ let Some ( elem_geo) =
708+ workspace. element_geometry ( & mapped)
709+ else {
710+ return ;
711+ } ;
712+ elem_geo. loc . to_global ( & workspace. output )
713+ } else {
714+ return ;
715+ } ;
716+ let cursor = seat
717+ . get_pointer ( )
718+ . unwrap ( )
719+ . current_location ( )
720+ . to_i32_round ( ) ;
721+
722+ shell. menu_request (
723+ & surface,
724+ & seat,
725+ serial,
726+ cursor - position. as_logical ( ) ,
727+ false ,
728+ & state. common . config ,
729+ & state. common . event_loop_handle ,
730+ false ,
731+ )
732+ } else {
733+ None
734+ } ;
735+ drop ( shell) ;
736+
737+ dispatch_grab ( grab, seat, serial, state) ;
738+ } ) ;
739+ }
740+
680741 if let Some ( mouse_button) = mouse_button {
681742 match mouse_button {
682743 smithay:: backend:: input:: MouseButton :: Left => {
@@ -703,56 +764,84 @@ impl State {
703764 } ,
704765 ) ;
705766 }
706- smithay:: backend:: input:: MouseButton :: Right => {
767+ smithay:: backend:: input:: MouseButton :: Middle => {
707768 supress_button ( ) ;
708- self . common . event_loop_handle . insert_idle (
709- move |state| {
710- let mut shell =
711- state. common . shell . write ( ) . unwrap ( ) ;
712- let Some ( target_elem) =
713- shell. element_for_surface ( & surface)
714- else {
715- return ;
716- } ;
717- let Some ( geom) =
718- shell. space_for ( target_elem) . and_then (
719- |f| f. element_geometry ( target_elem) ,
720- )
721- else {
722- return ;
723- } ;
724- let geom = geom. to_f64 ( ) ;
725- let center =
726- geom. loc + geom. size . downscale ( 2.0 ) ;
727- let offset = center. to_global ( & output)
728- - global_position;
729- let edge = match (
730- offset. x > 0.0 ,
731- offset. y > 0.0 ,
732- ) {
733- ( true , true ) => ResizeEdge :: TOP_LEFT ,
734- ( false , true ) => ResizeEdge :: TOP_RIGHT ,
735- ( true , false ) => {
736- ResizeEdge :: BOTTOM_LEFT
737- }
738- ( false , false ) => {
739- ResizeEdge :: BOTTOM_RIGHT
740- }
741- } ;
742- let res = shell. resize_request (
743- & surface,
744- & seat_clone,
745- serial,
746- edge,
747- false ,
748- ) ;
749- drop ( shell) ;
750- dispatch_grab (
751- res, seat_clone, serial, state,
752- ) ;
753- } ,
769+ window_menu (
770+ seat_clone,
771+ & self . common . event_loop_handle ,
772+ surface,
773+ serial,
754774 ) ;
755775 }
776+ smithay:: backend:: input:: MouseButton :: Right => {
777+ supress_button ( ) ;
778+ if seat
779+ . get_keyboard ( )
780+ . unwrap ( )
781+ . modifier_state ( )
782+ . shift
783+ {
784+ window_menu (
785+ seat_clone,
786+ & self . common . event_loop_handle ,
787+ surface,
788+ serial,
789+ ) ;
790+ } else {
791+ self . common . event_loop_handle . insert_idle (
792+ move |state| {
793+ let mut shell =
794+ state. common . shell . write ( ) . unwrap ( ) ;
795+ let Some ( target_elem) =
796+ shell. element_for_surface ( & surface)
797+ else {
798+ return ;
799+ } ;
800+ let Some ( geom) = shell
801+ . space_for ( target_elem)
802+ . and_then ( |f| {
803+ f. element_geometry ( target_elem)
804+ } )
805+ else {
806+ return ;
807+ } ;
808+ let geom = geom. to_f64 ( ) ;
809+ let center =
810+ geom. loc + geom. size . downscale ( 2.0 ) ;
811+ let offset = center. to_global ( & output)
812+ - global_position;
813+ let edge = match (
814+ offset. x > 0.0 ,
815+ offset. y > 0.0 ,
816+ ) {
817+ ( true , true ) => {
818+ ResizeEdge :: TOP_LEFT
819+ }
820+ ( false , true ) => {
821+ ResizeEdge :: TOP_RIGHT
822+ }
823+ ( true , false ) => {
824+ ResizeEdge :: BOTTOM_LEFT
825+ }
826+ ( false , false ) => {
827+ ResizeEdge :: BOTTOM_RIGHT
828+ }
829+ } ;
830+ let res = shell. resize_request (
831+ & surface,
832+ & seat_clone,
833+ serial,
834+ edge,
835+ false ,
836+ ) ;
837+ drop ( shell) ;
838+ dispatch_grab (
839+ res, seat_clone, serial, state,
840+ ) ;
841+ } ,
842+ ) ;
843+ }
844+ }
756845 _ => { }
757846 }
758847 }
@@ -786,8 +875,6 @@ impl State {
786875 } ,
787876 ) ;
788877 ptr. frame ( self ) ;
789- } else if event. state ( ) == ButtonState :: Released {
790- ptr. unset_grab ( self , serial, event. time_msec ( ) )
791878 }
792879 }
793880 InputEvent :: PointerAxis { event, .. } => {
0 commit comments