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

Transparent background for tooltips, dropdowns etc. #1583

Merged
merged 5 commits into from
Feb 18, 2021
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
36 changes: 35 additions & 1 deletion druid-shell/src/platform/gtk/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ pub(crate) struct WindowBuilder {
min_size: Option<Size>,
resizable: bool,
show_titlebar: bool,
transparent: bool,
}

#[derive(Clone)]
Expand All @@ -137,6 +138,7 @@ pub(crate) struct WindowState {
window: ApplicationWindow,
scale: Cell<Scale>,
area: Cell<ScaledArea>,
is_transparent: Cell<bool>,
/// Used to determine whether to honor close requests from the system: we inhibit them unless
/// this is true, and this gets set to true when our client requests a close.
closing: Cell<bool>,
Expand Down Expand Up @@ -180,6 +182,7 @@ impl WindowBuilder {
min_size: None,
resizable: true,
show_titlebar: true,
transparent: false,
}
}

Expand All @@ -203,6 +206,10 @@ impl WindowBuilder {
self.show_titlebar = show_titlebar;
}

pub fn set_transparent(&mut self, transparent: bool) {
self.transparent = transparent;
}

pub fn set_position(&mut self, position: Point) {
self.position = Some(position);
}
Expand Down Expand Up @@ -232,7 +239,16 @@ impl WindowBuilder {

window.set_title(&self.title);
window.set_resizable(self.resizable);
window.set_app_paintable(true);
window.set_decorated(self.show_titlebar);
let mut can_transparent = false;
if self.transparent {
if let Some(screen) = window.get_screen() {
let visual = screen.get_rgba_visual();
can_transparent = visual.is_some();
window.set_visual(visual.as_ref());
}
}

// Get the scale factor based on the GTK reported DPI
let scale_factor =
Expand All @@ -254,6 +270,7 @@ impl WindowBuilder {
window,
scale: Cell::new(scale),
area: Cell::new(area),
is_transparent: Cell::new(self.transparent & can_transparent),
closing: Cell::new(false),
drawing_area,
surface: RefCell::new(None),
Expand Down Expand Up @@ -409,6 +426,19 @@ impl WindowBuilder {
Inhibit(false)
}));

win_state.drawing_area.connect_screen_changed(
clone!(handle => move |widget, _prev_screen| {
if let Some(state) = handle.state.upgrade() {

if let Some(screen) = widget.get_screen(){
let visual = screen.get_rgba_visual();
state.is_transparent.set(visual.is_some());
widget.set_visual(visual.as_ref());
}
}
}),
);

win_state.drawing_area.connect_button_press_event(clone!(handle => move |_widget, event| {
if let Some(state) = handle.state.upgrade() {
state.with_handler(|handler| {
Expand Down Expand Up @@ -712,7 +742,11 @@ impl WindowState {
*surface = None;

if let Some(w) = self.drawing_area.get_window() {
*surface = w.create_similar_surface(cairo::Content::Color, width, height);
if self.is_transparent.get() {
*surface = w.create_similar_surface(cairo::Content::ColorAlpha, width, height);
} else {
*surface = w.create_similar_surface(cairo::Content::Color, width, height);
}
if surface.is_none() {
return Err(anyhow!("create_similar_surface failed"));
}
Expand Down
15 changes: 13 additions & 2 deletions druid-shell/src/platform/mac/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use std::time::Instant;

use block::ConcreteBlock;
use cocoa::appkit::{
CGFloat, NSApp, NSApplication, NSAutoresizingMaskOptions, NSBackingStoreBuffered, NSEvent,
NSView, NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowStyleMask,
CGFloat, NSApp, NSApplication, NSAutoresizingMaskOptions, NSBackingStoreBuffered, NSColor,
NSEvent, NSView, NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowStyleMask,
};
use cocoa::base::{id, nil, BOOL, NO, YES};
use cocoa::foundation::{
Expand Down Expand Up @@ -119,6 +119,7 @@ pub(crate) struct WindowBuilder {
window_state: Option<WindowState>,
resizable: bool,
show_titlebar: bool,
transparent: bool,
}

#[derive(Clone)]
Expand Down Expand Up @@ -170,6 +171,7 @@ impl WindowBuilder {
window_state: None,
resizable: true,
show_titlebar: true,
transparent: false,
}
}

Expand All @@ -193,6 +195,10 @@ impl WindowBuilder {
self.show_titlebar = show_titlebar;
}

pub fn set_transparent(&mut self, transparent: bool) {
self.transparent = transparent;
}

pub fn set_level(&mut self, level: WindowLevel) {
self.level = Some(level);
}
Expand Down Expand Up @@ -246,6 +252,11 @@ impl WindowBuilder {
window.setContentMinSize_(size);
}

if self.transparent {
window.setOpaque_(NO);
window.setBackgroundColor_(NSColor::clearColor(nil));
}

window.setTitle_(make_nsstring(&self.title));

let (view, idle_queue) = make_view(self.handler.expect("view"));
Expand Down
4 changes: 4 additions & 0 deletions druid-shell/src/platform/web/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ impl WindowBuilder {
// Ignored
}

pub fn set_transparent(&mut self, _transparent: bool) {
// Ignored
}

pub fn set_position(&mut self, _position: Point) {
// Ignored
}
Expand Down
7 changes: 6 additions & 1 deletion druid-shell/src/platform/windows/paint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub(crate) unsafe fn create_render_target_dxgi(
d2d_factory: &D2DFactory,
swap_chain: *mut IDXGISwapChain1,
scale: Scale,
transparent: bool,
) -> Result<DxgiSurfaceRenderTarget, Error> {
let mut buffer: *mut IDXGISurface = null_mut();
as_result((*swap_chain).GetBuffer(
Expand All @@ -57,7 +58,11 @@ pub(crate) unsafe fn create_render_target_dxgi(
_type: D2D1_RENDER_TARGET_TYPE_DEFAULT,
pixelFormat: D2D1_PIXEL_FORMAT {
format: DXGI_FORMAT_B8G8R8A8_UNORM,
alphaMode: D2D1_ALPHA_MODE_IGNORE,
alphaMode: if transparent {
D2D1_ALPHA_MODE_PREMULTIPLIED
} else {
D2D1_ALPHA_MODE_IGNORE
},
},
dpiX: (scale.x() * SCALE_TARGET_DPI) as f32,
dpiY: (scale.y() * SCALE_TARGET_DPI) as f32,
Expand Down
18 changes: 18 additions & 0 deletions druid-shell/src/platform/windows/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ use std::ptr;
use std::slice;

use lazy_static::lazy_static;
use winapi::ctypes::c_void;
use winapi::shared::dxgi::IDXGIDevice;
use winapi::shared::guiddef::REFIID;
use winapi::shared::minwindef::{BOOL, HMODULE, UINT};
use winapi::shared::ntdef::{HRESULT, LPWSTR};
use winapi::shared::windef::{HMONITOR, HWND, RECT};
Expand Down Expand Up @@ -147,6 +150,11 @@ type GetSystemMetricsForDpi =
// from shcore.dll
type GetDpiForMonitor = unsafe extern "system" fn(HMONITOR, MONITOR_DPI_TYPE, *mut UINT, *mut UINT);
type SetProcessDpiAwareness = unsafe extern "system" fn(PROCESS_DPI_AWARENESS) -> HRESULT;
type DCompositionCreateDevice = unsafe extern "system" fn(
dxgiDevice: *const IDXGIDevice,
iid: REFIID,
dcompositionDevice: *mut *mut c_void,
) -> HRESULT;

#[allow(non_snake_case)] // For member fields
pub struct OptionalFunctions {
Expand All @@ -156,6 +164,7 @@ pub struct OptionalFunctions {
pub GetDpiForMonitor: Option<GetDpiForMonitor>,
pub SetProcessDpiAwareness: Option<SetProcessDpiAwareness>,
pub GetSystemMetricsForDpi: Option<GetSystemMetricsForDpi>,
pub DCompositionCreateDevice: Option<DCompositionCreateDevice>,
}

#[allow(non_snake_case)] // For local variables
Expand Down Expand Up @@ -201,13 +210,15 @@ fn load_optional_functions() -> OptionalFunctions {

let shcore = load_library("shcore.dll");
let user32 = load_library("user32.dll");
let dcomp = load_library("dcomp.dll");

let mut GetDpiForSystem = None;
let mut GetDpiForMonitor = None;
let mut GetDpiForWindow = None;
let mut SetProcessDpiAwarenessContext = None;
let mut SetProcessDpiAwareness = None;
let mut GetSystemMetricsForDpi = None;
let mut DCompositionCreateDevice = None;

if shcore.is_null() {
tracing::info!("No shcore.dll");
Expand All @@ -225,13 +236,20 @@ fn load_optional_functions() -> OptionalFunctions {
load_function!(user32, GetSystemMetricsForDpi, "10");
}

if dcomp.is_null() {
tracing::info!("No dcomp.dll");
} else {
load_function!(dcomp, DCompositionCreateDevice, "8.1");
}

OptionalFunctions {
GetDpiForSystem,
GetDpiForWindow,
SetProcessDpiAwarenessContext,
GetDpiForMonitor,
SetProcessDpiAwareness,
GetSystemMetricsForDpi,
DCompositionCreateDevice,
}
}

Expand Down
Loading