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

Implement set_maximized, get_current_monitor, set_fullscreen and set_decorations for windows #457

Merged
merged 18 commits into from Apr 12, 2018

Conversation

@edwin0cheng
Copy link
Contributor

commented Apr 10, 2018

No description provided.

@edwin0cheng edwin0cheng changed the title Implement set_maximized, set_fullscreen and set_decorations for windows Implement set_maximized, get_current_monitor, set_fullscreen and set_decorations for windows Apr 10, 2018

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 11, 2018

Should fixed part of the #72

@edwin0cheng edwin0cheng referenced this pull request Apr 11, 2018

Open

Roadmap to 0.1.2 (WIP) #43

0 of 9 tasks complete
@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 11, 2018

Thanks so much for this! This will be useful for a lot of people.

I won't have time to give this a full review until later today, though what I've looked at so far looks good. However, this needs a CHANGELOG entry.

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 11, 2018

Thanks , and CHANGELOG entry added.

And here is some implementation details about this PR;

  1. Same as #270, we remove supports for changing screen native resolution when WindowBuilder::with_fullscreen was set. It is more consistent with others platforms implementation and more stable. (however it is a breaking change)
  2. The whole set_fullscreen function are based on chrome's implemetation.
  3. The ITaskbarList COM interface stuffs i had made a PR in upstream winapi crate retep998/winapi-rs#592. i would make another PR when new winapi version released.
  4. Based on how current threading model works, all window sized events have to be called from main thread, so you would see all SetWindowPos is wrapped by execute_in_thread.
@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 11, 2018

Just a minor bug first for rust-stable (I use nightly) and added support for with_maximized. (So that with_decorations, with_fullscreen all works now).

It should be completed. Thanks :)

@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 11, 2018

After testing this on Windows 10, everything works as expected. However, I've succeeded in breaking things: while toggling either decorations or fullscreen rapidly repeatedly, the window in question eventually freezes. My other windows don't freeze, continuing to play their animations, but as soon as one of those windows is focused (in other words, as soon as it interacts with the backend), it freezes as well. This can happen using your updated fullscreen example program, though it's far easier to reproduce if you change the key handlers to respond to Pressed rather than Released, since then you can simply hold down the key and encounter the problem very readily. This fortunately isn't an issue with maximization.

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 11, 2018

@francesca64 I changed the fullscreen example use PRESSED and I just tested this and it should works now.

By the way, the cause of freezes are related to this block, which i didn't fully understand why it would write in this way. A quick search lead me to PR #250.

@francesca64
Copy link
Collaborator

left a comment

Excellent work! Not only does everything work fine now, but after reviewing every single line, I haven't found any real mistakes.

That said, I do have some changes to request. They're all pretty minor, and most of them are related to formatting/maintainability, so they won't take very long.

// See : https://stackoverflow.com/questions/10740346/setforegroundwindow-only-working-while-visual-studio-is-open
const ALT : i32 = 0xA4;
const EXTENDEDKEY : u32 = 0x1;
const KEYUP : u32 = 0x2;
winuser::keybd_event(ALT as _, 0x45, EXTENDEDKEY | 0, 0);

// Simulate a key release
winuser::keybd_event(0xA4, 0x45, EXTENDEDKEY | KEYUP, 0);

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

keybd_event has been superseded by SendInput, which can also be used to send both events at once.

I saw the 0x45 scancode used in the example you linked, but judging by the official example, it's actually the scancode for numlock. For getting the correct scancode, MapVirtualKey looks appropriate.

} else {
(None, None)
};
let (x, y) = (None, None);

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

This doesn't appear to have any use anymore, since it will always just get unwrap_or'd to CW_USEDEFAULT in the call to CreateWindowExW.

@@ -1,5 +1,6 @@
# Unreleased

- Implement Window::set_fullscreen, Window::set_maximized and Window::set_decorations for windows.

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator
  • Don't forget about WindowBuilder::with_maximized
  • WindowBuilder::with_fullscreen no longer changing display resolution is an important behavior change
  • Windows should be capitalized, to prevent ambiguity
  • Use backticks to format method names/etc. as code
{
unsafe {
let boxed = Box::new(function) as Box<FnMut(_)>;
let boxed2 = Box::new(boxed);

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

It would be good to have a comment that makes it more obvious that the double-boxing is intentional, as it looks very surprising to anyone who's not already well-acquainted with the backend.

This comment has been minimized.

Copy link
@edwin0cheng

edwin0cheng Apr 12, 2018

Author Contributor

This execute_in_thread function i just copy from EventsLoop::execute_in_thread. Maybe i should copy the comment as well? Or i should refactor it out as a common implementation function ?

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

Refactoring would be lovely.

let raw = Box::into_raw(boxed2);

let res = winuser::PostThreadMessageA(self.thread_id, *EXEC_MSG_ID,
raw as *mut () as usize as WPARAM, 0);

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

For calls that can't fit on one line, it's standard to have each argument on its own line with a trailing comma.

let win = Window {
window: real_window,
window_state: window_state,
events_loop_proxy

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

Missing trailing comma

// And because ShowWindow will resize the window
// We call it in the main thread
self.events_loop_proxy.execute_in_thread(move |_| {
winuser::ShowWindow(window.0, if maximized { winuser::SW_MAXIMIZE } else {winuser::SW_RESTORE} );

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

Formatting:

winuser::ShowWindow(window.0, if maximized { winuser::SW_MAXIMIZE } else { winuser::SW_RESTORE });

There's a similar formatting issue at the end of mark_fullscreen, so please address it there as well.

}

unsafe impl Send for Window {}
unsafe impl Sync for Window {}

// https://blogs.msdn.microsoft.com/oldnewthing/20131017-00/?p=2903

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

While I doubt this will 404 any time soon, it's always good to explain things in comments.

@@ -1,4 +1,7 @@
#![cfg(target_os = "windows")]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#![allow(dead_code)]

This comment has been minimized.

Copy link
@francesca64

francesca64 Apr 12, 2018

Collaborator

I'd prefer if you used #[allow(dead_code)] per-definition rather than for the whole module.

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

Done ^^

@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 12, 2018

Magnificent! I can tell you went above and beyond to make things cleaner.

I was ready to merge this, but I've found one more bug. Here are the steps to reproduce:

  1. Run fullscreen example program
  2. Turn off decorations
  3. Exit fullscreen
  4. Attempt to turn decorations back on (it doesn't work until the 3rd press)

The same thing happens with toggling maximization while in fullscreen, though that only takes 2 presses.

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

Good catch, but im away from keyboard now, would check it tonight(asia time), thanks

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

@francesca64 It should be fixed :)

@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 12, 2018

Great, I've confirmed that it's fixed.

Here's another bug:

  1. Run fullscreen example program
  2. Exit fullscreen
  3. Press key to maximize
  4. Enter fullscreen
  5. Press key to un-maximize
  6. Exit fullscreen
  7. (Window will still be maximized) press key to un-maximize; nothing happens until the second press

This fortunately doesn't happen for decoration toggling.

Using the built-in maximization button causes things like this to happen:

  1. Run fullscreen example program
  2. Exit fullscreen
  3. Press the window's maximization button
  4. Press key to un-maximize; nothing happens until the second press

It's also important to account for the user un-maximizing the window by moving it:

  1. Run fullscreen example program
  2. Exit fullscreen
  3. Press key to maximize
  4. Move window to un-maximize
  5. Press key to maximize; nothing happens until the second press
@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

Using the built-in maximization button causes things like this to happen:

Run fullscreen example program
Exit fullscreen
Press the window's maximization button
Press key to un-maximize; nothing happens until the second press

It's also important to account for the user un-maximizing the window by moving it:

Run fullscreen example program
Exit fullscreen
Press key to maximize
Move window to un-maximize
Press key to maximize; nothing happens until the second press

It is because the fullscreen example just use a bool to indicate Maximize status, which is not sync to the system status. And we do not have an api to query this status. : )

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

Run fullscreen example program
Exit fullscreen
Press key to maximize
Enter fullscreen
Press key to un-maximize
Exit fullscreen
(Window will still be maximized) press key to un-maximize; nothing happens until the second press

9f52ed1 should fixed this

@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 12, 2018

Right, good point about it being an issue in the example and not your implementation, sorry about that.

While it does fix my first issue, there are still issues with the wrong state being restored after using the built-in maximization button or moving to un-maximize.

  1. Run fullscreen example program
  2. Exit fullscreen
  3. Press the window's maximization button
  4. Enter fullscreen
  5. Exit fullscreen
  6. The window is no longer maximized

and:

  1. Run fullscreen example program
  2. Press key to maximize
  3. Exit fullscreen
  4. Move window to un-maximize
  5. Enter fullscreen
  6. Exit fullscreen
  7. The window is maximized
@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

Sorry about that, the maximized state is a little bit tricky to implement correctly. Anyway, it should be fixed all the issues listed.

@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 12, 2018

Awesome! This is the last thing, I promise: in the CHANGELOG, you accidentally put WindowBuilder::set_maximized instead of WindowBuilder::with_maximized.

@edwin0cheng

This comment has been minimized.

Copy link
Contributor Author

commented Apr 12, 2018

Sorry about that, thank you so much to help me to catch out these bugs. It will be my second closed PR :)

@francesca64

This comment has been minimized.

Copy link
Collaborator

commented Apr 12, 2018

No problem! This PR is very much appreciated.

@francesca64 francesca64 merged commit bdc01fe into rust-windowing:master Apr 12, 2018

4 of 5 checks passed

continuous-integration/travis-ci/pr The Travis CI build is in progress
Details
ci/circleci: android-test Your tests passed on CircleCI!
Details
ci/circleci: asmjs-test Your tests passed on CircleCI!
Details
ci/circleci: wasm-test Your tests passed on CircleCI!
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details

@edwin0cheng edwin0cheng deleted the edwin0cheng:windows-fullscreen branch Apr 12, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.