1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-18 10:52:16 +03:00

add beginnings of painting

This commit is contained in:
Wez Furlong 2019-08-08 12:02:03 -07:00
parent f2928053aa
commit de7446b172
3 changed files with 158 additions and 5 deletions

View File

@ -0,0 +1,106 @@
use crate::bitmaps::BitmapImage;
use failure::Fallible;
use std::io::Error as IoError;
use winapi::shared::windef::*;
use winapi::um::wingdi::*;
pub struct GdiBitmap {
hdc: HDC,
hbitmap: HBITMAP,
data: *mut u8,
width: usize,
height: usize,
}
impl BitmapImage for GdiBitmap {
unsafe fn pixel_data(&self) -> *const u8 {
self.data
}
unsafe fn pixel_data_mut(&mut self) -> *mut u8 {
self.data
}
fn image_dimensions(&self) -> (usize, usize) {
(self.width, self.height)
}
}
impl Drop for GdiBitmap {
fn drop(&mut self) {
unsafe {
DeleteObject(self.hbitmap as _);
}
unsafe {
DeleteObject(self.hdc as _);
}
}
}
impl GdiBitmap {
pub fn hdc(&self) -> HDC {
self.hdc
}
pub fn hbitmap(&self) -> HBITMAP {
self.hbitmap
}
pub fn new_compatible(width: usize, height: usize, hdc: HDC) -> Fallible<Self> {
let hdc = unsafe { CreateCompatibleDC(hdc) };
if hdc.is_null() {
let err = IoError::last_os_error();
failure::bail!("CreateCompatibleDC: {}", err);
}
let mut data = std::ptr::null_mut();
let bmi = BITMAPINFO {
bmiHeader: BITMAPINFOHEADER {
biSize: std::mem::size_of::<BITMAPINFOHEADER>() as u32,
biPlanes: 1,
biBitCount: 32,
biWidth: width as i32,
biHeight: height as i32,
biClrImportant: 0,
biClrUsed: 0,
biCompression: 0,
biSizeImage: width as u32 * height as u32 * 4,
biXPelsPerMeter: 0,
biYPelsPerMeter: 0,
},
bmiColors: [RGBQUAD {
rgbBlue: 0,
rgbRed: 0,
rgbGreen: 0,
rgbReserved: 0,
}],
};
let hbitmap = unsafe {
CreateDIBSection(
hdc,
&bmi,
DIB_RGB_COLORS,
&mut data,
std::ptr::null_mut(),
0,
)
};
if hbitmap.is_null() {
let err = IoError::last_os_error();
failure::bail!("CreateDIBSection: {}", err);
}
unsafe {
SelectObject(hdc, hbitmap as _);
}
Ok(Self {
hdc,
hbitmap,
data: data as *mut u8,
width,
height,
})
}
}

View File

@ -1,3 +1,4 @@
pub mod gdi;
pub mod window; pub mod window;
/// Convert a rust string to a windows wide string /// Convert a rust string to a windows wide string

View File

@ -1,4 +1,6 @@
use super::gdi::*;
use super::*; use super::*;
use crate::bitmaps::*;
use failure::Fallible; use failure::Fallible;
use std::io::Error as IoError; use std::io::Error as IoError;
use std::ptr::{null, null_mut}; use std::ptr::{null, null_mut};
@ -6,6 +8,7 @@ use std::sync::{Arc, Mutex};
use winapi::shared::minwindef::*; use winapi::shared::minwindef::*;
use winapi::shared::windef::*; use winapi::shared::windef::*;
use winapi::um::libloaderapi::GetModuleHandleW; use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::wingdi::*;
use winapi::um::winuser::*; use winapi::um::winuser::*;
pub trait WindowCallbacks { pub trait WindowCallbacks {
@ -30,6 +33,14 @@ pub struct Window {
inner: Arc<Mutex<WindowInner>>, inner: Arc<Mutex<WindowInner>>,
} }
fn rect_width(r: &RECT) -> i32 {
r.right - r.left
}
fn rect_height(r: &RECT) -> i32 {
r.bottom - r.top
}
fn adjust_client_to_window_dimensions(width: usize, height: usize) -> (i32, i32) { fn adjust_client_to_window_dimensions(width: usize, height: usize) -> (i32, i32) {
let mut rect = RECT { let mut rect = RECT {
left: 0, left: 0,
@ -39,9 +50,7 @@ fn adjust_client_to_window_dimensions(width: usize, height: usize) -> (i32, i32)
}; };
unsafe { AdjustWindowRect(&mut rect, WS_POPUP | WS_SYSMENU | WS_CAPTION, 0) }; unsafe { AdjustWindowRect(&mut rect, WS_POPUP | WS_SYSMENU | WS_CAPTION, 0) };
let width = rect.right - rect.left; (rect_width(&rect), rect_height(&rect))
let height = rect.bottom - rect.top;
(width, height)
} }
fn arc_to_pointer(arc: &Arc<Mutex<WindowInner>>) -> *const Mutex<WindowInner> { fn arc_to_pointer(arc: &Arc<Mutex<WindowInner>>) -> *const Mutex<WindowInner> {
@ -229,10 +238,47 @@ fn enable_dark_mode(hwnd: HWND) {
} }
} }
unsafe fn wm_paint(hwnd: HWND, _msg: UINT, _wparam: WPARAM, _lparam: LPARAM) -> Option<LRESULT> {
if let Some(_inner) = arc_from_hwnd(hwnd) {
let dc = GetDC(hwnd);
let mut rect = RECT {
left: 0,
bottom: 0,
right: 0,
top: 0,
};
GetClientRect(hwnd, &mut rect);
let width = rect_width(&rect) as usize;
let height = rect_height(&rect) as usize;
let mut bitmap = GdiBitmap::new_compatible(width, height, dc).unwrap();
bitmap.clear(Color::rgb(0, 0, 0));
BitBlt(
dc,
0,
0,
width as i32,
height as i32,
bitmap.hdc(),
0,
0,
SRCCOPY,
);
ValidateRect(hwnd, std::ptr::null());
Some(0)
} else {
None
}
}
unsafe fn do_wnd_proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> Option<LRESULT> { unsafe fn do_wnd_proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> Option<LRESULT> {
match msg { match msg {
WM_NCCREATE => return wm_nccreate(hwnd, msg, wparam, lparam), WM_NCCREATE => wm_nccreate(hwnd, msg, wparam, lparam),
WM_NCDESTROY => return wm_ncdestroy(hwnd, msg, wparam, lparam), WM_NCDESTROY => wm_ncdestroy(hwnd, msg, wparam, lparam),
WM_PAINT => wm_paint(hwnd, msg, wparam, lparam),
WM_CLOSE => { WM_CLOSE => {
if let Some(inner) = arc_from_hwnd(hwnd) { if let Some(inner) = arc_from_hwnd(hwnd) {
let mut inner = inner.lock().unwrap(); let mut inner = inner.lock().unwrap();