Skip to content

Commit

Permalink
feat: allow setting webview bg color, closes #197 (#682)
Browse files Browse the repository at this point in the history
* feat: allow setting webview bg color, closes #197

* update docs

* fix build

* Update src/webview/mod.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>

* Update src/webview/mod.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>

* Update src/webview/mod.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>

* Update src/webview/mod.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>

* Update src/webview/mod.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>

* Update src/webview/mod.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>

* use if else

* remove macos implementation

* add android impl

* use RGBA type alias, create CreateWebViewAttributes struct for android

* update docs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>
  • Loading branch information
amrbashir and lucasfernog committed Sep 5, 2022
1 parent 9dfffcf commit eb1b723
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 27 deletions.
5 changes: 5 additions & 0 deletions .changes/webview-bg-color.md
@@ -0,0 +1,5 @@
---
"wry": "patch"
---

Allow setting the webview background color.
54 changes: 52 additions & 2 deletions src/webview/android/main_pipe.rs
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use crate::webview::RGBA;
use crossbeam_channel::*;
use once_cell::sync::Lazy;
use std::os::unix::prelude::*;
Expand Down Expand Up @@ -40,7 +41,13 @@ impl MainPipe<'_> {
let activity = self.activity.as_obj();
if let Ok(message) = CHANNEL.1.recv() {
match message {
WebViewMessage::CreateWebView(url, devtools) => {
WebViewMessage::CreateWebView(attrs) => {
let CreateWebViewAttributes {
url,
devtools,
transparent,
background_color,
} = attrs;
// Create webview
let rust_webview_class = find_my_class(
env,
Expand Down Expand Up @@ -72,6 +79,14 @@ impl MainPipe<'_> {
&[devtools.into()],
)?;

if transparent {
set_background_color(env, webview, (0, 0, 0, 0))?;
} else {
if let Some(color) = background_color {
set_background_color(env, webview, color)?;
}
}

// Create and set webview client
let rust_webview_client_class = find_my_class(
env,
Expand Down Expand Up @@ -118,6 +133,11 @@ impl MainPipe<'_> {
)?;
}
}
WebViewMessage::SetBackgroundColor(background_color) => {
if let Some(webview) = &self.webview {
set_background_color(env, webview.as_obj(), background_color)?;
}
}
}
}
Ok(())
Expand All @@ -141,8 +161,38 @@ fn find_my_class<'a>(
Ok(my_class.into())
}

fn set_background_color<'a>(
env: JNIEnv<'a>,
webview: JObject<'a>,
background_color: RGBA,
) -> Result<(), JniError> {
let color_class = env.find_class("android/graphics/Color")?;
let color = env.call_static_method(
color_class,
"argb",
"(IIII)I",
&[
background_color.3.into(),
background_color.0.into(),
background_color.1.into(),
background_color.2.into(),
],
)?;
env.call_method(webview, "setBackgroundColor", "(I)V", &[color])?;
Ok(())
}

#[derive(Debug)]
pub enum WebViewMessage {
CreateWebView(String, bool),
CreateWebView(CreateWebViewAttributes),
Eval(String),
SetBackgroundColor(RGBA),
}

#[derive(Debug)]
pub struct CreateWebViewAttributes {
pub url: String,
pub devtools: bool,
pub transparent: bool,
pub background_color: Option<RGBA>,
}
20 changes: 15 additions & 5 deletions src/webview/android/mod.rs
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use super::{WebContext, WebViewAttributes};
use super::{WebContext, WebViewAttributes, RGBA};
use crate::{
application::window::Window,
http::{header::HeaderValue, Request as HttpRequest, Response as HttpResponse},
Expand All @@ -20,7 +20,7 @@ use tao::platform::android::ndk_glue::{

pub(crate) mod binding;
mod main_pipe;
use main_pipe::{MainPipe, WebViewMessage, MAIN_PIPE};
use main_pipe::{CreateWebViewAttributes, MainPipe, WebViewMessage, MAIN_PIPE};

#[macro_export]
macro_rules! android_binding {
Expand Down Expand Up @@ -107,6 +107,8 @@ impl InnerWebView {
ipc_handler,
devtools,
custom_protocols,
background_color,
transparent,
..
} = attributes;

Expand All @@ -123,7 +125,12 @@ impl InnerWebView {
.replace(&format!("{}://", name), &format!("https://{}.", name))
}

MainPipe::send(WebViewMessage::CreateWebView(url_string, devtools));
MainPipe::send(WebViewMessage::CreateWebView(CreateWebViewAttributes {
url: url_string,
devtools,
background_color,
transparent,
}));
}

REQUEST_HANDLER.get_or_init(move || {
Expand Down Expand Up @@ -193,8 +200,6 @@ impl InnerWebView {
Ok(())
}

pub fn focus(&self) {}

#[cfg(any(debug_assertions, feature = "devtools"))]
pub fn open_devtools(&self) {}

Expand All @@ -207,6 +212,11 @@ impl InnerWebView {
}

pub fn zoom(&self, _scale_factor: f64) {}

pub fn set_background_color(&self, background_color: RGBA) -> Result<()> {
MainPipe::send(WebViewMessage::SetBackgroundColor(background_color));
Ok(())
}
}

pub fn platform_webview_version() -> Result<String> {
Expand Down
58 changes: 56 additions & 2 deletions src/webview/mod.rs
Expand Up @@ -61,8 +61,23 @@ pub struct WebViewAttributes {
pub user_agent: Option<String>,
/// Whether the WebView window should be visible.
pub visible: bool,
/// Whether the WebView should be transparent. Not supported on Windows 7.
/// Whether the WebView should be transparent.
///
/// ## Platform-specific:
///
/// **Windows 7**: Not supported.
pub transparent: bool,
/// Specify the webview background color. This will be ignored if `transparent` is set to `true`.
///
/// The color uses the RGBA format.
///
/// ## Platform-specific:
///
/// - **macOS / iOS**: Not implemented.
/// - **Windows**:
/// - On Windows 7, transparency is not supported and the alpha value will be ignored.
/// - On Windows higher than 7: translucent colors are not supported so any alpha value other than `0` will be replaced by `255`
pub background_color: Option<RGBA>,
/// Whether load the provided URL to [`WebView`].
pub url: Option<Url>,
/// Whether page zooming by hotkeys is enabled
Expand Down Expand Up @@ -175,6 +190,7 @@ impl Default for WebViewAttributes {
user_agent: None,
visible: true,
transparent: false,
background_color: None,
url: None,
html: None,
initialization_scripts: vec![],
Expand All @@ -190,6 +206,11 @@ impl Default for WebViewAttributes {
}
}

/// Type alias for a color in the RGBA format.
///
/// Each value can be 0..255 inclusive.
pub type RGBA = (u8, u8, u8, u8);

/// Builder type of [`WebView`].
///
/// [`WebViewBuilder`] / [`WebView`] are the basic building blocks to construct WebView contents and
Expand All @@ -214,12 +235,31 @@ impl<'a> WebViewBuilder<'a> {
})
}

/// Sets whether the WebView should be transparent. Not supported on Windows 7.
/// Sets whether the WebView should be transparent.
///
/// ## Platform-specific:
///
/// **Windows 7**: Not supported.
pub fn with_transparent(mut self, transparent: bool) -> Self {
self.webview.transparent = transparent;
self
}

/// Specify the webview background color. This will be ignored if `transparent` is set to `true`.
///
/// The color uses the RGBA format.
///
/// ## Platfrom-specific:
///
/// - **macOS / iOS**: Not implemented.
/// - **Windows**:
/// - on Windows 7, transparency is not supported and the alpha value will be ignored.
/// - on Windows higher than 7: translucent colors are not supported so any alpha value other than `0` will be replaced by `255`
pub fn with_background_color(mut self, background_color: RGBA) -> Self {
self.webview.background_color = Some(background_color);
self
}

/// Sets whether the WebView should be transparent.
pub fn with_visible(mut self, visible: bool) -> Self {
self.webview.visible = visible;
Expand Down Expand Up @@ -535,6 +575,20 @@ impl WebView {
pub fn zoom(&self, scale_factor: f64) {
self.webview.zoom(scale_factor);
}

/// Specify the webview background color.
///
/// The color uses the RGBA format.
///
/// ## Platfrom-specific:
///
/// - **macOS / iOS**: Not implemented.
/// - **Windows**:
/// - On Windows 7, transparency is not supported and the alpha value will be ignored.
/// - On Windows higher than 7: translucent colors are not supported so any alpha value other than `0` will be replaced by `255`
pub fn set_background_color(&self, background_color: RGBA) -> Result<()> {
self.webview.set_background_color(background_color)
}
}

/// An event enumeration sent to [`FileDropHandler`].
Expand Down
26 changes: 23 additions & 3 deletions src/webview/webkitgtk/mod.rs
Expand Up @@ -13,7 +13,7 @@ use std::{
rc::Rc,
};

use gdk::{Cursor, EventMask, WindowEdge, RGBA};
use gdk::{Cursor, EventMask, WindowEdge};
use gio::Cancellable;
use glib::signal::Inhibit;
use gtk::prelude::*;
Expand All @@ -31,7 +31,7 @@ pub use web_context::WebContextImpl;

use crate::{
application::{platform::unix::*, window::Window},
webview::{web_context::WebContext, WebViewAttributes},
webview::{web_context::WebContext, WebViewAttributes, RGBA},
Error, Result,
};

Expand Down Expand Up @@ -271,7 +271,17 @@ impl InnerWebView {

// Transparent
if attributes.transparent {
webview.set_background_color(&RGBA::new(0., 0., 0., 0.));
webview.set_background_color(&gdk::RGBA::new(0., 0., 0., 0.));
} else {
// background color
if let Some(background_color) = attributes.background_color {
webview.set_background_color(&gdk::RGBA::new(
background_color.0 as _,
background_color.1 as _,
background_color.2 as _,
background_color.3 as _,
));
}
}

// File drop handling
Expand Down Expand Up @@ -392,6 +402,16 @@ impl InnerWebView {
pub fn zoom(&self, scale_factor: f64) {
WebViewExt::set_zoom_level(&*self.webview, scale_factor);
}

pub fn set_background_color(&self, background_color: RGBA) -> Result<()> {
self.webview.set_background_color(&gdk::RGBA::new(
background_color.0 as _,
background_color.1 as _,
background_color.2 as _,
background_color.3 as _,
));
Ok(())
}
}

pub fn platform_webview_version() -> Result<String> {
Expand Down
51 changes: 37 additions & 14 deletions src/webview/webview2/mod.rs
Expand Up @@ -5,7 +5,7 @@
mod file_drop;

use crate::{
webview::{WebContext, WebViewAttributes},
webview::{WebContext, WebViewAttributes, RGBA},
Error, Result,
};

Expand Down Expand Up @@ -189,21 +189,16 @@ impl InnerWebView {
let webview =
unsafe { controller.CoreWebView2() }.map_err(webview2_com::Error::WindowsError)?;

// background color
if !attributes.transparent {
if let Some(background_color) = attributes.background_color {
set_background_color(&controller, background_color)?;
}
}

// Transparent
if attributes.transparent && !is_windows_7() {
let controller2: ICoreWebView2Controller2 = controller
.cast()
.map_err(webview2_com::Error::WindowsError)?;
unsafe {
controller2
.SetDefaultBackgroundColor(COREWEBVIEW2_COLOR {
R: 0,
G: 0,
B: 0,
A: 0,
})
.map_err(webview2_com::Error::WindowsError)?;
}
set_background_color(&controller, (0, 0, 0, 0))?;
}

// The EventRegistrationToken is an out-param from all of the event registration calls. We're
Expand Down Expand Up @@ -704,12 +699,40 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
pub fn zoom(&self, scale_factor: f64) {
let _ = unsafe { self.controller.SetZoomFactor(scale_factor) };
}

pub fn set_background_color(&self, background_color: RGBA) -> Result<()> {
set_background_color(&self.controller, background_color).map_err(Into::into)
}
}

fn encode_wide(string: impl AsRef<std::ffi::OsStr>) -> Vec<u16> {
string.as_ref().encode_wide().chain(once(0)).collect()
}

pub fn set_background_color(
controller: &ICoreWebView2Controller,
background_color: RGBA,
) -> webview2_com::Result<()> {
let mut color = background_color;
if !is_windows_7() || color.3 != 0 {
color.3 = 255;
}

let controller2: ICoreWebView2Controller2 = controller
.cast()
.map_err(webview2_com::Error::WindowsError)?;
unsafe {
controller2
.SetDefaultBackgroundColor(COREWEBVIEW2_COLOR {
R: color.0,
G: color.1,
B: color.2,
A: color.3,
})
.map_err(webview2_com::Error::WindowsError)
}
}

pub fn platform_webview_version() -> Result<String> {
let mut versioninfo = PWSTR::null();
unsafe { GetAvailableCoreWebView2BrowserVersionString(PCWSTR::null(), &mut versioninfo) }
Expand Down

0 comments on commit eb1b723

Please sign in to comment.