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

Screen Module, window titlebar, position, size, DPI #1037

Merged
merged 21 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ You can find its changes [documented below](#060---2020-06-01).
### Highlights

### Added

- Windows: Added Screen module to get information about monitors and the screen. ([#1037] by [@rhzk])
- Added documentation to resizable() and show_titlebar() in WindowDesc. ([#1037] by [@rhzk])
- Windows: Added internal functions to handle Re-entrancy. ([#1037] by [@rhzk])
- Windows: WindowDesc: Create window with disabled titlebar, maximized or minimized state, and with position. ([#1037] by [@rhzk])
- Windows: WindowHandle: Change window state. Toggle titlebar. Change size and position of window. ([#1037] by [@rhzk])
- Windows: WindowHandle: Added handle_titlebar(), Allowing a custom titlebar to behave like the OS one. ([#1037] by [@rhzk])
- `OPEN_PANEL_CANCELLED` and `SAVE_PANEL_CANCELLED` commands. ([#1061] by @cmyr)
- Export `Image` and `ImageData` by default. ([#1011] by [@covercash2])
- Re-export `druid_shell::Scalable` under `druid` namespace. ([#1075] by [@ForLoveOfCats])
Expand All @@ -29,6 +36,8 @@ You can find its changes [documented below](#060---2020-06-01).

### Changed

- Windows: Improved DPI handling. Druid should now redraw correctly when dpi changes. ([#1037] by [@rhzk])
- windows: Window created with OS default size if not set. ([#1037] by [@rhzk])
- `Scale::from_scale` to `Scale::new`, and `Scale` methods `scale_x` / `scale_y` to `x` / `y`. ([#1042] by [@xStrom])
- Major rework of keyboard event handling. ([#1049] by [@raphlinus])
- `Container::rounded` takes `KeyOrValue<f64>` instead of `f64`. ([#1054] by [@binomial0])
Expand Down Expand Up @@ -288,6 +297,7 @@ Last release without a changelog :(
[@sysint64]: https://github.com/sysint64
[@justinmoon]: https://github.com/justinmoon
[@rjwittams]: https://github.com/rjwittams
[@rhzk]: https://github.com/rhzk
[@koutoftimer]: https://github.com/koutoftimer

[#599]: https://github.com/linebender/druid/pull/599
Expand Down Expand Up @@ -390,6 +400,7 @@ Last release without a changelog :(
[#1018]: https://github.com/linebender/druid/pull/1018
[#1025]: https://github.com/linebender/druid/pull/1025
[#1028]: https://github.com/linebender/druid/pull/1028
[#1037]: https://github.com/linebender/druid/pull/1037
[#1042]: https://github.com/linebender/druid/pull/1042
[#1043]: https://github.com/linebender/druid/pull/1043
[#1049]: https://github.com/linebender/druid/pull/1049
Expand Down
6 changes: 5 additions & 1 deletion druid-shell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ mod mouse;
mod platform;
mod region;
mod scale;
mod screen;
mod window;

pub use application::{AppHandler, Application};
Expand All @@ -61,6 +62,9 @@ pub use menu::Menu;
pub use mouse::{Cursor, MouseButton, MouseButtons, MouseEvent};
pub use region::Region;
pub use scale::{Scalable, Scale, ScaledArea};
pub use window::{IdleHandle, IdleToken, TimerToken, WinHandler, WindowBuilder, WindowHandle};
pub use screen::{Monitor, Screen};
pub use window::{
IdleHandle, IdleToken, TimerToken, WinHandler, WindowBuilder, WindowHandle, WindowState,
};

pub use keyboard_types;
1 change: 1 addition & 0 deletions druid-shell/src/platform/gtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ pub mod keycodes;
pub mod menu;
pub mod util;
pub mod window;
pub mod screen;
22 changes: 22 additions & 0 deletions druid-shell/src/platform/gtk/screen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2020 The Druid Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! GTK Monitors and Screen information.

use crate::screen::Monitor;

pub(crate) fn get_monitors() -> Vec<Monitor> {
log::warn!("Screen::get_monitors() is currently unimplemented for gtk.");
Vec::new()
}
40 changes: 40 additions & 0 deletions druid-shell/src/platform/gtk/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use crate::mouse::{Cursor, MouseButton, MouseButtons, MouseEvent};
use crate::region::Region;
use crate::scale::{Scalable, Scale, ScaledArea};
use crate::window::{IdleToken, TimerToken, WinHandler};
use crate::window;

use super::application::Application;
use super::dialog;
Expand Down Expand Up @@ -176,6 +177,14 @@ impl WindowBuilder {
self.show_titlebar = show_titlebar;
}

pub fn set_position(&mut self, _position: Point) {
log::warn!("WindowBuilder::set_position is currently unimplemented for gtk.");
}

pub fn set_window_state(&self, _state: window::WindowState) {
log::warn!("WindowBuilder::set_window_state is currently unimplemented for gtk.");
}

pub fn set_title(&mut self, title: impl Into<String>) {
self.title = title.into();
}
Expand Down Expand Up @@ -666,6 +675,37 @@ impl WindowHandle {
}
}

pub fn set_position(&self, _position: Point) {
log::warn!("WindowHandle::set_position is currently unimplemented for gtk.");
}

pub fn get_position(&self) -> Point {
log::warn!("WindowHandle::get_position is currently unimplemented for gtk.");
Point::new(0.0, 0.0)
}

pub fn set_size(&self, _size: Size) {
log::warn!("WindowHandle::set_size is currently unimplemented for gtk.");
}

pub fn get_size(&self) -> Size {
log::warn!("WindowHandle::get_size is currently unimplemented for gtk.");
Size::new(0.0, 0.0)
}

pub fn set_window_state(&self, _state: window::WindowState) {
log::warn!("WindowHandle::set_window_state is currently unimplemented for gtk.");
}

pub fn get_window_state(&self) -> window::WindowState {
log::warn!("WindowHandle::get_window_state is currently unimplemented for gtk.");
window::WindowState::RESTORED
}

pub fn handle_titlebar(&self, _val: bool) {
log::warn!("WindowHandle::handle_titlebar is currently unimplemented for gtk.");
}

/// Close the window.
pub fn close(&self) {
if let Some(state) = self.state.upgrade() {
Expand Down
1 change: 1 addition & 0 deletions druid-shell/src/platform/mac/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ mod keyboard;
pub mod menu;
pub mod util;
pub mod window;
pub mod screen;
22 changes: 22 additions & 0 deletions druid-shell/src/platform/mac/screen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2020 The Druid Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! macOS Monitors and Screen information.

use crate::screen::Monitor;

pub(crate) fn get_monitors() -> Vec<Monitor> {
log::warn!("Screen::get_monitors() is currently unimplemented for Mac.");
Vec::new()
}
41 changes: 41 additions & 0 deletions druid-shell/src/platform/mac/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ use crate::mouse::{Cursor, MouseButton, MouseButtons, MouseEvent};
use crate::region::Region;
use crate::scale::Scale;
use crate::window::{IdleToken, TimerToken, WinHandler};
use crate::window;
use crate::Error;


#[allow(non_upper_case_globals)]
const NSWindowDidBecomeKeyNotification: &str = "NSWindowDidBecomeKeyNotification";

Expand Down Expand Up @@ -149,6 +151,14 @@ impl WindowBuilder {
self.show_titlebar = show_titlebar;
}

pub fn set_position(&mut self, _position: Point) {
log::warn!("WindowBuilder::set_position is currently unimplemented for mac platforms.");
}

pub fn set_window_state(&self, _state: window::WindowState) {
log::warn!("WindowBuilder::set_window_state is currently unimplemented for mac platforms.");
}

pub fn set_title(&mut self, title: impl Into<String>) {
self.title = title.into();
}
Expand Down Expand Up @@ -866,6 +876,37 @@ impl WindowHandle {
// TODO: Implement this
pub fn show_titlebar(&self, _show_titlebar: bool) {}

pub fn set_position(&self, _position: Point) {
log::warn!("WindowHandle::set_position is currently unimplemented for Mac.");
}

pub fn get_position(&self) -> Point {
log::warn!("WindowHandle::get_position is currently unimplemented for Mac.");
Point::new(0.0, 0.0)
}

pub fn set_size(&self, _size: Size) {
log::warn!("WindowHandle::set_size is currently unimplemented for Mac.");
}

pub fn get_size(&self) -> Size {
log::warn!("WindowHandle::get_size is currently unimplemented for Mac.");
Size::new(0.0, 0.0)
}

pub fn set_window_state(&self, _state: window::WindowState) {
log::warn!("WindowHandle::set_window_state is currently unimplemented for Mac.");
}

pub fn get_window_state(&self) -> window::WindowState {
log::warn!("WindowHandle::get_window_state is currently unimplemented for Mac.");
window::WindowState::RESTORED
}

pub fn handle_titlebar(&self, _val: bool) {
log::warn!("WindowHandle::handle_titlebar is currently unimplemented for Mac.");
}

pub fn resizable(&self, resizable: bool) {
unsafe {
let window: id = msg_send![*self.nsview.load(), window];
Expand Down
1 change: 1 addition & 0 deletions druid-shell/src/platform/web/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ pub mod error;
pub mod keycodes;
pub mod menu;
pub mod window;
pub mod screen;
22 changes: 22 additions & 0 deletions druid-shell/src/platform/web/screen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2020 The Druid Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Monitor and Screen information ignored for web.

use crate::screen::Monitor;

pub(crate) fn get_monitors() -> Vec<Monitor> {
log::warn!("Screen::get_monitors() is not implemented for web.");
Vec::new()
}
40 changes: 40 additions & 0 deletions druid-shell/src/platform/web/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use crate::keyboard::{KbKey, KeyState, Modifiers};
use crate::mouse::{Cursor, MouseButton, MouseButtons, MouseEvent};
use crate::region::Region;
use crate::window::{IdleToken, TimerToken, WinHandler};
use crate::window;

// This is a macro instead of a function since KeyboardEvent and MouseEvent has identical functions
// to query modifier key states.
Expand Down Expand Up @@ -348,6 +349,14 @@ impl WindowBuilder {
// Ignored
}

pub fn set_position(&mut self, _position: Point) {
// Ignored
}

pub fn set_window_state(&self, _state: window::WindowState) {
// Ignored
}

pub fn set_title<S: Into<String>>(&mut self, title: S) {
self.title = title.into();
}
Expand Down Expand Up @@ -433,6 +442,37 @@ impl WindowHandle {
log::warn!("show_titlebar unimplemented for web");
}

pub fn set_position(&self, _position: Point) {
log::warn!("WindowHandle::set_position unimplemented for web");
}

pub fn get_position(&self) -> Point {
log::warn!("WindowHandle::get_position unimplemented for web.");
Point::new(0.0, 0.0)
}

pub fn set_size(&self, _size: Size) {
log::warn!("WindowHandle::set_size unimplemented for web.");
}

pub fn get_size(&self) -> Size {
log::warn!("WindowHandle::get_size unimplemented for web.");
Size::new(0.0, 0.0)
}

pub fn set_window_state(&self, _state: window::WindowState) {
log::warn!("WindowHandle::set_window_state unimplemented for web.");
}

pub fn get_window_state(&self) -> window::WindowState {
log::warn!("WindowHandle::get_window_state unimplemented for web.");
window::WindowState::RESTORED
}

pub fn handle_titlebar(&self, _val: bool) {
log::warn!("WindowHandle::handle_titlebar unimplemented for web.");
}

pub fn close(&self) {
// TODO
}
Expand Down
24 changes: 18 additions & 6 deletions druid-shell/src/platform/windows/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ use std::rc::Rc;

use winapi::shared::minwindef::{FALSE, HINSTANCE};
use winapi::shared::ntdef::LPCWSTR;
use winapi::shared::windef::{HCURSOR, HWND};
use winapi::shared::windef::{HCURSOR, HWND, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2};
use winapi::shared::winerror::HRESULT_FROM_WIN32;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::shellscalingapi::PROCESS_SYSTEM_DPI_AWARE;
use winapi::um::shellscalingapi::PROCESS_PER_MONITOR_DPI_AWARE;
use winapi::um::winuser::{
DispatchMessageW, GetAncestor, GetMessageW, LoadIconW, PostMessageW, PostQuitMessage,
RegisterClassW, TranslateAcceleratorW, TranslateMessage, GA_ROOT, IDI_APPLICATION, MSG,
WNDCLASSW,
WNDCLASSW, SendMessageW
};

use crate::application::AppHandler;
Expand All @@ -38,7 +38,7 @@ use super::accels;
use super::clipboard::Clipboard;
use super::error::Error;
use super::util::{self, ToWide, CLASS_NAME, OPTIONAL_FUNCTIONS};
use super::window::{self, DS_REQUEST_DESTROY};
use super::window::{self, DS_REQUEST_DESTROY, DS_HANDLE_DEFERRED};

#[derive(Clone)]
pub(crate) struct Application {
Expand All @@ -50,6 +50,8 @@ struct State {
windows: HashSet<HWND>,
}



impl Application {
pub fn new() -> Result<Application, Error> {
Application::init()?;
Expand All @@ -64,10 +66,15 @@ impl Application {
fn init() -> Result<(), Error> {
// TODO: Report back an error instead of panicking
util::attach_console();
if let Some(func) = OPTIONAL_FUNCTIONS.SetProcessDpiAwareness {
if let Some(func) = OPTIONAL_FUNCTIONS.SetProcessDpiAwarenessContext {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do have a concern here. The old implementation worked on Windows 8.1 (the comment was wrong), now it seems like there won't be any dpi.

A related concern is that this function will fail on Windows 10 versions previous to 1703, and will result in no dpi scaling. I think fallback handling based on the optional function should take care of this though.

Also, we should probably at least log an error return value, though I think runtime failure is not likely. That's certainly on me from the old code though :)

// This function is only supported on windows 10
unsafe {
func(PROCESS_SYSTEM_DPI_AWARE); // TODO: per monitor (much harder)
func(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
}
else if let Some(func) = OPTIONAL_FUNCTIONS.SetProcessDpiAwareness {
unsafe {
func(PROCESS_PER_MONITOR_DPI_AWARE);
}
}
unsafe {
Expand Down Expand Up @@ -105,6 +112,11 @@ impl Application {
unsafe {
// Handle windows messages
loop {
if let Ok(state) = self.state.try_borrow() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My experience is that putting any additional functionality in the runloop is problematic. The logic doesn't get invoked when the system is using its own runloop, which happens on live resize and also while a file dialog is open. Also, if and when we ever run as a guest (for example as a VST plugin), then we'll also be at the mercy of the host's runloop. But if we use the function sparingly, maybe we're ok.

Also, I think the name "DS_HANDLE_DROPPED" is confusing and should be changed to "BLOCKED" to be consistent with other functions.

See below where I suggest a comment to add.

for hwnd in &state.windows {
SendMessageW(*hwnd, DS_HANDLE_DEFERRED, 0,0);
}
}
let mut msg = mem::MaybeUninit::uninit();
let res = GetMessageW(msg.as_mut_ptr(), ptr::null_mut(), 0, 0);
if res <= 0 {
Expand Down
Loading