Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the show system menu method to window #3109

Merged
merged 22 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a908daf
Added the show system menu method to window
YouKnow-sys Sep 21, 2023
0f7aab2
Apply suggestions from code review
YouKnow-sys Sep 22, 2023
5485d97
removed the comment
YouKnow-sys Sep 22, 2023
c45763c
Update src/window.rs
YouKnow-sys Sep 22, 2023
57082d9
updated the `drag_window` example
YouKnow-sys Sep 22, 2023
cbd3013
added wikipedia page for windows system menu
YouKnow-sys Sep 22, 2023
f308c0c
Apply suggestions from code review
YouKnow-sys Sep 23, 2023
345971d
updated `show_window_menu` to allow receiving a custom position as well
YouKnow-sys Sep 23, 2023
671b03b
format the code
YouKnow-sys Sep 23, 2023
3e91384
changed `mouse` to `cursor`.
YouKnow-sys Sep 23, 2023
b23b669
removed unused map
YouKnow-sys Sep 23, 2023
fbb074b
Apply suggestions from code review
YouKnow-sys Sep 23, 2023
1dcb1b6
Merge branch 'master' into master
YouKnow-sys Sep 23, 2023
3068e80
Merge branch 'master' into master
YouKnow-sys Sep 23, 2023
42bf1bd
removed the ability to show window menu at current mouse position
YouKnow-sys Oct 4, 2023
2a776e7
Merge branch 'master' of https://github.com/YouKnow-sys/winit
YouKnow-sys Oct 4, 2023
df63cb6
Update CHANGELOG.md
YouKnow-sys Oct 4, 2023
3e83e8f
Merge branch 'master' into master
YouKnow-sys Oct 4, 2023
9009dfd
fixed the code to not warn on `unsafe_op_in_unsafe_fn` lint
YouKnow-sys Oct 4, 2023
a6641f8
Merge branch 'master' of https://github.com/YouKnow-sys/winit
YouKnow-sys Oct 4, 2023
a17e99c
Merge branch 'master' into master
YouKnow-sys Oct 10, 2023
b3fd0b3
Fix docs compilation
kchibisov Oct 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ And please only add new entries to the top of this list, right below the `# Unre
- On Web, add `EventLoopWindowTargetExtWebSys` and `PollStrategy`, which allows to set different strategies for `ControlFlow::Poll`. By default the Prioritized Task Scheduling API is used, but an option to use `Window.requestIdleCallback` is available as well. Both use `setTimeout()`, with a trick to circumvent throttling to 4ms, as a fallback.
- Implement `PartialOrd` and `Ord` for `MouseButton`.
- On X11, fix event loop not waking up on `ControlFlow::Poll` and `ControlFlow::WaitUntil`.
- Add `Window::show_window_menu()` which shows the system menu at the mouse position. Currently only implemented on Windows.

# 0.29.1-beta

Expand Down
34 changes: 27 additions & 7 deletions examples/drag_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ fn main() -> Result<(), impl std::error::Error> {
Event::WindowEvent { event, window_id } => match event {
WindowEvent::CloseRequested => elwt.exit(),
WindowEvent::MouseInput {
state: ElementState::Pressed,
button: MouseButton::Left,
state,
button,
..
} => {
let window = if (window_id == window_1.id() && switched)
Expand All @@ -40,7 +40,11 @@ fn main() -> Result<(), impl std::error::Error> {
&window_1
};

window.drag_window().unwrap()
match (button, state) {
(MouseButton::Left, ElementState::Pressed) => window.drag_window().unwrap(),
(MouseButton::Right, ElementState::Released) => window.show_window_menu(),
_ => ()
}
}
WindowEvent::CursorEntered { .. } => {
entered_id = window_id;
Expand All @@ -54,10 +58,26 @@ fn main() -> Result<(), impl std::error::Error> {
..
},
..
} if c == "x" => {
switched = !switched;
name_windows(entered_id, switched, &window_1, &window_2);
println!("Switched!")
} => {
match c.as_str() {
"x" => {
switched = !switched;
name_windows(entered_id, switched, &window_1, &window_2);
println!("Switched!")
},
"d" => {
let window = if (window_id == window_1.id() && switched)
|| (window_id == window_2.id() && !switched)
{
&window_2
} else {
&window_1
};

window.set_decorations(!window.is_decorated());
}
_ => ()
}
}
WindowEvent::RedrawRequested => {
if window_id == window_1.id() {
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,9 @@ impl Window {
))
}

#[inline]
pub fn show_window_menu(&self) {}

pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(
error::NotSupportedError::new(),
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/ios/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ impl Inner {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}

#[inline]
pub fn show_window_menu(&self) {}

pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,9 @@ impl Window {
x11_or_wayland!(match self; Window(window) => window.drag_resize_window(direction))
}

#[inline]
pub fn show_window_menu(&self) {}

#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
x11_or_wayland!(match self; Window(w) => w.set_cursor_hittest(hittest))
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,9 @@ impl WinitWindow {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}

#[inline]
pub fn show_window_menu(&self) {}

#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
self.setIgnoresMouseEvents(!hittest);
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/orbital/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@ impl Window {
))
}

#[inline]
pub fn show_window_menu(&self) {}

#[inline]
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/web/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ impl Inner {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}

#[inline]
pub fn show_window_menu(&self) {}

#[inline]
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
Expand Down
86 changes: 79 additions & 7 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ use windows_sys::Win32::{
Touch::{RegisterTouchWindow, TWF_WANTPALM},
},
WindowsAndMessaging::{
CreateWindowExW, FlashWindowEx, GetClientRect, GetCursorPos, GetForegroundWindow,
GetSystemMetrics, GetWindowPlacement, GetWindowTextLengthW, GetWindowTextW,
IsWindowVisible, LoadCursorW, PeekMessageW, PostMessageW, RegisterClassExW, SetCursor,
SetCursorPos, SetForegroundWindow, SetWindowDisplayAffinity, SetWindowPlacement,
SetWindowPos, SetWindowTextW, CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, FLASHWINFO,
CreateWindowExW, EnableMenuItem, FlashWindowEx, GetClientRect, GetCursorPos,
GetForegroundWindow, GetSystemMenu, GetSystemMetrics, GetWindowPlacement,
GetWindowTextLengthW, GetWindowTextW, IsWindowVisible, LoadCursorW, PeekMessageW,
PostMessageW, RegisterClassExW, SetCursor, SetCursorPos, SetForegroundWindow,
SetMenuDefaultItem, SetWindowDisplayAffinity, SetWindowPlacement, SetWindowPos,
SetWindowTextW, TrackPopupMenu, CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, FLASHWINFO,
FLASHW_ALL, FLASHW_STOP, FLASHW_TIMERNOFG, FLASHW_TRAY, GWLP_HINSTANCE, HTBOTTOM,
HTBOTTOMLEFT, HTBOTTOMRIGHT, HTCAPTION, HTLEFT, HTRIGHT, HTTOP, HTTOPLEFT, HTTOPRIGHT,
NID_READY, PM_NOREMOVE, SM_DIGITIZER, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOSIZE,
SWP_NOZORDER, WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WM_NCLBUTTONDOWN, WNDCLASSEXW,
MENU_ITEM_STATE, MFS_DISABLED, MFS_ENABLED, MF_BYCOMMAND, NID_READY, PM_NOREMOVE,
SC_CLOSE, SC_MAXIMIZE, SC_MINIMIZE, SC_MOVE, SC_RESTORE, SC_SIZE, SM_DIGITIZER,
SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOSIZE, SWP_NOZORDER, TPM_LEFTALIGN,
TPM_RETURNCMD, WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WM_NCLBUTTONDOWN, WM_SYSCOMMAND,
WNDCLASSEXW,
},
},
};
Expand Down Expand Up @@ -471,6 +475,74 @@ impl Window {
Ok(())
}

unsafe fn handle_showing_window_menu(&self) {
let points = {
let mut pos = mem::zeroed();
GetCursorPos(&mut pos);
pos
};

// get the current system menu
let h_menu = GetSystemMenu(self.hwnd(), 0);
if h_menu == 0 {
warn!("The corresponding window doesn't have a system menu");
// This situation should not be treated as an error so just return without showing menu.
return;
}

fn enable(b: bool) -> MENU_ITEM_STATE {
if b {
MFS_ENABLED
} else {
MFS_DISABLED
}
}

// Change the menu items according to the current window status.

let restore_btn = enable(self.is_maximized() && self.is_resizable());
let size_btn = enable(!self.is_maximized() && self.is_resizable());
let maximize_btn = enable(!self.is_maximized() && self.is_resizable());

EnableMenuItem(h_menu, SC_RESTORE, MF_BYCOMMAND | restore_btn);
EnableMenuItem(h_menu, SC_MOVE, MF_BYCOMMAND | enable(!self.is_maximized()));
EnableMenuItem(h_menu, SC_SIZE, MF_BYCOMMAND | size_btn);
EnableMenuItem(h_menu, SC_MINIMIZE, MF_BYCOMMAND | MFS_ENABLED);
EnableMenuItem(h_menu, SC_MAXIMIZE, MF_BYCOMMAND | maximize_btn);
EnableMenuItem(h_menu, SC_CLOSE, MF_BYCOMMAND | MFS_ENABLED);

// Set the default menu item.
SetMenuDefaultItem(h_menu, SC_CLOSE, 0);

// Popup the system menu at the position.
let result = TrackPopupMenu(
h_menu,
TPM_RETURNCMD | TPM_LEFTALIGN, // for now im using LTR, but we have to use user layout direction
points.x,
points.y,
0,
self.hwnd(),
std::ptr::null_mut(),
);

if result == 0 {
// User canceled the menu, no need to continue.
return;
}

// Send the command that the user select to the corresponding window.
if PostMessageW(self.hwnd(), WM_SYSCOMMAND, result as _, 0) == 0 {
warn!("Can't post the system menu message to the window.");
}
}

#[inline]
pub fn show_window_menu(&self) {
unsafe {
self.handle_showing_window_menu();
}
}

#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
let window = self.window.clone();
Expand Down
13 changes: 13 additions & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,19 @@ impl Window {
.maybe_wait_on_main(|w| w.drag_resize_window(direction))
}

/// Show window menu at current mouse position.
///
YouKnow-sys marked this conversation as resolved.
Show resolved Hide resolved
/// There's no guarantee that calling this method show the window menu.
///
YouKnow-sys marked this conversation as resolved.
Show resolved Hide resolved
/// ## Platform-specific
YouKnow-sys marked this conversation as resolved.
Show resolved Hide resolved
/// - **Windows:** Window need to have `WS_SYSMENU` window style to be able to show the [`window menu`].
/// - **Android / iOS / macOS / Orbital / Wayland / Web / X11:** Unsupported.
YouKnow-sys marked this conversation as resolved.
Show resolved Hide resolved
///
/// [`window menu`]: https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu
YouKnow-sys marked this conversation as resolved.
Show resolved Hide resolved
YouKnow-sys marked this conversation as resolved.
Show resolved Hide resolved
pub fn show_window_menu(&self) {
self.window.maybe_queue_on_main(|w| w.show_window_menu())
}

/// Modifies whether the window catches cursor events.
///
/// If `true`, the window will catch the cursor events. If `false`, events are passed through
Expand Down