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

Tracking Issue: DPI Usability Upgrades #939

Closed
8 of 12 tasks
Osspial opened this issue Jun 19, 2019 · 36 comments
Closed
8 of 12 tasks

Tracking Issue: DPI Usability Upgrades #939

Osspial opened this issue Jun 19, 2019 · 36 comments
Labels
D - average Likely as difficult as most tasks here H - help wanted Someone please save us I - BLOCKING RELEASE Prevents a new release P - high Vital to have S - api Design and usability S - enhancement Wouldn't this be the coolest? S - meta Project governance

Comments

@Osspial
Copy link
Contributor

Osspial commented Jun 19, 2019

This issue tracks the implementation of the HiDPI API changes that were discussed in #837. PRs implementing this change should be made against the dpi-overhaul branch, and we'll merge that branch onto master once it's implemented on all platforms.

@Osspial Osspial added D - average Likely as difficult as most tasks here H - good first issue Ideal for new contributors DS - ios DS - macos DS - wayland DS - windows DS - x11 P - high Vital to have H - help wanted Someone please save us S - api Design and usability S - enhancement Wouldn't this be the coolest? labels Jun 19, 2019
@Osspial
Copy link
Contributor Author

Osspial commented Jun 19, 2019

Mentoring Instructions

For the most part, implementing this should be a matter of following the error messages and converting to physical or logical coordinates as necessary.

Once the main implementation for a platform is complete, this may be a good place to look into fixing #940. However, that isn't strictly necessary if you aren't feeling up to it.

@goddessfreya
Copy link
Contributor

goddessfreya commented Jun 25, 2019

So, I had to make this diagram to explain to someone why things got a lifetime, enjoy folks:

@felixrabe
Copy link
Contributor

felixrabe commented Jun 25, 2019

@zegentzy Awesome!

Could you somehow scale it down a tiny little bit (like, 10x)? I can't even fit it on one screen at max zoomed-out level in Firefox (30%). (https://imgur.com/a/yy6Qvk6) I don't have Inkscape installed right now to do it myself.

(I guess it is ironic that a diagram about DPI issues has ... DPI issues :) )

@goddessfreya
Copy link
Contributor

@goddessfreya
Copy link
Contributor

@murarth Do you have an interest in picking up this issue?

@murarth
Copy link
Contributor

murarth commented Jul 26, 2019

I have a question about the addition of new_inner_size: &mut Option<PhysicalSize> to the HiDpiFactorChanged event: What is the advantage of allowing applications to pass a size value this way versus calling Window::set_inner_size?

@goddessfreya
Copy link
Contributor

It allows smooth resizing. Otherwise HiDpiFactorChanged would change the size once, then the users would change it once, causing the window's size to flicker.

@murarth
Copy link
Contributor

murarth commented Jul 26, 2019

What if, for platforms that support setting window size at the time of DPI change, the implementation were to track DPI change state and the event loop could use a size value provided by a Window::set_inner_size call made during the handling of the DPI change event? I've provided a pseudocode example to demonstrate what I mean by this:

struct Window {
    /// Tracks whether the event loop is currently handling a DPI change for this window
    is_handling_dpi_change: bool,
    /// Contains a new size for the new DPI, provided by the application
    dpi_change_size: Option<PhysicalSize>,
    // ...
}

impl Window {
    pub fn set_inner_size(&self, size: PhysicalSize) {
        if self.is_handling_dpi_change {
            // If a DPI change event is currently being handled,
            // provide the size value to the event loop.
            self.dpi_change_size = Some(size);
        } else {
            // Otherwise, the window is resized in the usual manner
        }
    }
}

impl EventLoop {
    fn run<F>(&self, callback: F) {
        loop {
            match receive_platform_event() {
                DpiChanged(window, new_dpi) => {
                    window.is_handling_dpi_change = true;

                    callback(WindowEvent::HiDpiFactorChanged(new_dpi));

                    window.is_handling_dpi_change = false;

                    let new_size = window.dpi_change_size.take()
                        .unwrap_or(/* Use size value suggested by the platform */);

                    // Respond to platform DPI change event with `new_size` value
                }
                // ...
            }
        }
    }
}

I feel that, while this solution may add some complexity to internal platform code, it may be less than the complexity of adding a lifetime parameter to the Event type. Additionally, it may be worthwhile to keep the public API simple.

I will admit, though, that I'm being a bit selfish in prosposing this, as I think the X11 event loop in particular may need significant changes to adapt to a lifetime parameter in the Event type. I'm certainly willing to implement the API as currently designed, but such changes mean the possibility of introducing new bugs and that's not good for anyone.

@goddessfreya
Copy link
Contributor

@murarth I'm going to have to disagree with that proposal. As you mentioned that solution would add some considerate complexity to the internal code. In addition to that, I imagine it would be confusing for users that their calls to set_inner_size didn't change the size immediately.

Plus, it might not be obvious to users of the api that they need to call set_inner_size inside the dpi changed event for smooth resizing. Users could easily move it out of that call, and be confused why their window is flickering in size, ect.

@murarth
Copy link
Contributor

murarth commented Jul 31, 2019

@zegentzy Yeah. Fair enough. I'll get started on implementing this soon.

@murarth
Copy link
Contributor

murarth commented Aug 3, 2019

In the interest of avoiding more work down the road, I'd like to merge master into the dpi-overhaul branch. Would that be acceptable? If so, I can submit this as a separate PR.

@murarth
Copy link
Contributor

murarth commented Aug 8, 2019

I've submitted a PR for the merge with master (#1095). I can submit the X11/Wayland implementation once that is merged.

@murarth
Copy link
Contributor

murarth commented Aug 11, 2019

Never mind about merging master into dpi-overhaul. I don't think it would have reduced the work of the eventual merge, as both branches are still changing. Plus, I realize it would likely cause more headaches for those developing on that branch.

I've submitted a PR implementing this API for X11 and Wayland: #1098

@Osspial
Copy link
Contributor Author

Osspial commented Oct 5, 2019

@vbogaevsky What's the status on the iOS implementation?

@vbogaevsky
Copy link
Contributor

@Osspial, I'm completing draft this week. I will also have to rework macOS implementation after #1173.

@vbogaevsky
Copy link
Contributor

vbogaevsky commented Oct 13, 2019

I've created PR for iOS implementation of HiDpiEventChanged #1223 . But I did not test it.
Can we update dpi-overhaul branch from master? Then I'll fix macOS implementation, so that it works correctly with #1173 changes.

@Osspial
Copy link
Contributor Author

Osspial commented Oct 13, 2019

@vbogaevsky Yay! I'll rebase dpi-overhaul onto master, but you're likely going to have to fix up the macOS rebase. There were some merge conflicts, and I'm not confident I resolved them entirely correctly since I can't build for macOS.

@Osspial
Copy link
Contributor Author

Osspial commented Oct 13, 2019

@vbogaevsky You can find the WIP rebase on dpi-overhaul-wip-rebase - there are enough merge conflicts on non-Windows platforms that I can't confidently resolve them without introducing errors. I ended up just restarting the rebase and only resolving the Windows conflicts. @murarth Could you also see about resolving the Linux merge conflicts on that branch?

@murarth
Copy link
Contributor

murarth commented Oct 13, 2019

@Osspial I've resolved the conflicts. Shall I push directly to the branch or submit a PR (which will fail CI on every platform, as cargo fmt chokes on <<<<<<< lines in macos)?

@Osspial
Copy link
Contributor Author

Osspial commented Oct 13, 2019

@murarth force-pushing is fine

@murarth
Copy link
Contributor

murarth commented Oct 13, 2019

@Osspial I've pushed the changes to dpi-overhaul-wip-rebase.

@vbogaevsky
Copy link
Contributor

vbogaevsky commented Oct 13, 2019

@Osspial I'll then fix conflicts in dpi-overhaul-wip-rebase for macOS and open a PR since I can't push into original branches.

@Osspial
Copy link
Contributor Author

Osspial commented Oct 14, 2019

@murarth Thanks!

@vbogaevsky Now that you're a member, you should have push access to branches in the main repo.

@vbogaevsky
Copy link
Contributor

@Osspial, great! I'll finish with conflicts and push to dpi-overhaul-wip-rebase today.

@vbogaevsky
Copy link
Contributor

@Osspial, I've resolved macOS merge conflicts in dpi-overhaul-wip-rebase.

@Osspial
Copy link
Contributor Author

Osspial commented Oct 16, 2019

@vbogaevsky thanks! I've cleaned up the git history so we can avoid having commits with merge conflicts on master when dpi-overhaul gets merged, and pushed those changes to dpi-overhaul.

@tangmi
Copy link
Contributor

tangmi commented Oct 18, 2019

I'm unsure if hidpi on the web is already well understood, but I hope this comment can be helpful!

I recently hacked together hidpi support for the web on winit-legacy (along with some other web changes, tangmi/winit@341fe47...2e11615).

What I found worked was:

  • Treat CSS pixels as logical units
  • Treat the CanvasElement's actual size as physical units.
  • Use Window.devicePixelRatio to get the hidpi scale factor
    • e.g. If the desired dom size is 320x240 at a hidpi scale factor of 2x, the canvas element's size would be set to 640x480, while it's CSS size would be set to 320x240.
  • Input events are tracked in CSS pixels and should be treated as in logical units

Here's a JSFiddle of it all coming together.

Edit: If this seems like a reasonable way to support hidpi on web, I'm interested in working this into @ryanisaacg's excellent recent web support (if I can find some time! Please, beat me to it if someone else is also interested!).

Edit 2: I have a draft PR (#1233), which is mainly missing tests (how were the other backend's hidpi settings tested?).

@Osspial
Copy link
Contributor Author

Osspial commented Nov 21, 2019

While we're making all these changes to the API, should we rename hidpi_factor to scale_factor? Personally, I've always had a hard time remembering the exact name for the function, and scale_factor seems much more intuitive than the current name.

@tangmi
Copy link
Contributor

tangmi commented Nov 21, 2019

@Osspial I don't have a strong opinion (as long as this value is documented as the scale from logical units to physical units!), but my gut feeling is that scale_factor might be a little ambiguous? Again, no strong opinion as long as we plan on keeping the (awesome) dpi module docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
D - average Likely as difficult as most tasks here H - help wanted Someone please save us I - BLOCKING RELEASE Prevents a new release P - high Vital to have S - api Design and usability S - enhancement Wouldn't this be the coolest? S - meta Project governance
Development

No branches or pull requests

9 participants