Skip to content

Commit

Permalink
webrender: show window cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
harryfei committed Aug 14, 2020
1 parent 9af3b4d commit e768f96
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 20 deletions.
120 changes: 120 additions & 0 deletions rust_src/src/webrender_backend/cursor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use super::output::OutputRef;

use crate::{
remacs_sys::{
draw_glyphs_face, draw_phys_cursor_glyph, get_phys_cursor_geometry, get_phys_cursor_glyph,
glyph_row, glyph_type,
},
windows::LispWindowRef,
};

pub fn draw_filled_cursor(mut window: LispWindowRef, row: *mut glyph_row) {
unsafe { draw_phys_cursor_glyph(window.as_mut(), row, draw_glyphs_face::DRAW_CURSOR) };
}

pub fn draw_hollow_box_cursor(mut window: LispWindowRef, row: *mut glyph_row) {
let cursor_glyph = unsafe { get_phys_cursor_glyph(window.as_mut()) };

if cursor_glyph.is_null() {
return;
}

let mut x: i32 = 0;
let mut y: i32 = 0;
let mut height: i32 = 0;
unsafe {
get_phys_cursor_geometry(
window.as_mut(),
row,
cursor_glyph,
&mut x,
&mut y,
&mut height,
)
};
let width = window.phys_cursor_width;

let frame = window.get_frame();
let output: OutputRef = unsafe { frame.output_data.wr.into() };

output.canvas().draw_hollow_box_cursor(x, y, width, height);
}

pub fn draw_bar_cursor(
mut window: LispWindowRef,
row: *mut glyph_row,
cursor_width: i32,
is_hbar: bool,
) {
let frame = window.get_frame();
let output: OutputRef = unsafe { frame.output_data.wr.into() };

let cursor_glyph = unsafe { get_phys_cursor_glyph(window.as_mut()) };

if cursor_glyph.is_null() {
return;
}

if unsafe {
(*cursor_glyph).type_() == glyph_type::XWIDGET_GLYPH
|| (*cursor_glyph).type_() == glyph_type::IMAGE_GLYPH
} {
return;
}

let face = unsafe {
let face_id = (*cursor_glyph).face_id();
let face_id = std::mem::transmute::<u32, crate::remacs_sys::face_id>(face_id);

&*frame.face_from_id(face_id).unwrap()
};

let (x, y, width, height) = if !is_hbar {
let mut x = window.text_to_frame_pixel_x(window.phys_cursor.x);
let y = window.frame_pixel_y(window.phys_cursor.y);

let width = if cursor_width < 0 {
frame.cursor_width
} else {
cursor_width
};

let width = std::cmp::min(unsafe { (*cursor_glyph).pixel_width } as i32, width);

window.phys_cursor_width = width;
// If the character under cursor is R2L, draw the bar cursor
// on the right of its glyph, rather than on the left.
if (unsafe { (*cursor_glyph).resolved_level() } & 1) != 0 {
x += unsafe { (*cursor_glyph).pixel_width } as i32 - width;
}

let height = unsafe { (*row).height };

(x, y, width, height)
} else {
let row_height = unsafe { (*row).height } as i32;
let mut x = window.text_to_frame_pixel_x(window.phys_cursor.x);

let height = if cursor_width < 0 {
unsafe { (*row).height }
} else {
cursor_width
};

let height = std::cmp::min(row_height, height);

if (unsafe { (*cursor_glyph).resolved_level() } & 1) != 0
&& unsafe { (*cursor_glyph).pixel_width } as i32 > window.phys_cursor_width - 1
{
x += unsafe { (*cursor_glyph).pixel_width } as i32 - window.phys_cursor_width + 1;
}

let y = window.frame_pixel_y(window.phys_cursor.y + row_height - height);

let width = window.phys_cursor_width - 1;

(x, y, width, height)
};

output.canvas().draw_bar_cursor(face, x, y, width, height);
}
13 changes: 12 additions & 1 deletion rust_src/src/webrender_backend/display_info.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use libc;
use std::ptr;

use crate::{frame::LispFrameRef, lisp::ExternalPtr, remacs_sys::wr_display_info};
use crate::{
frame::LispFrameRef,
lisp::ExternalPtr,
remacs_sys::{wr_display_info, XGCValues},
};

use super::{keyboard::KeyboardProcessor, output::OutputRef, term::TerminalRef};

Expand All @@ -12,6 +16,8 @@ pub struct DisplayInfoInner {
pub output: OutputRef,

pub keyboard_processor: KeyboardProcessor,

pub scratch_cursor_gc: Box<XGCValues>,
}

impl Default for DisplayInfoInner {
Expand All @@ -21,6 +27,11 @@ impl Default for DisplayInfoInner {
focus_frame: LispFrameRef::new(ptr::null_mut()),
output: OutputRef::new(ptr::null_mut()),
keyboard_processor: KeyboardProcessor::new(),
scratch_cursor_gc: Box::new(XGCValues {
foreground: 0,
background: 0,
font: ptr::null_mut(),
}),
}
}
}
Expand Down
109 changes: 103 additions & 6 deletions rust_src/src/webrender_backend/draw_canvas.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use webrender::{self, api::units::*, api::*};

use super::{color::pixel_to_color, font::WRFontRef, glyph::GlyphStringRef, output::OutputRef};
use super::{
color::{color_to_pixel, pixel_to_color},
display_info::DisplayInfoRef,
font::WRFontRef,
glyph::GlyphStringRef,
output::OutputRef,
};

use crate::{
remacs_sys::{
draw_fringe_bitmap_params, face, face_underline_type, glyph_row, glyph_type,
prepare_face_for_display,
draw_fringe_bitmap_params, draw_glyphs_face, face, face_underline_type, glyph_row,
glyph_type, prepare_face_for_display,
},
util::HandyDandyRectBuilder,
};
Expand All @@ -28,9 +34,54 @@ impl DrawCanvas {
pub fn draw_glyph_string(&mut self, mut s: GlyphStringRef) {
unsafe { prepare_face_for_display(s.f, s.face) };

let face = unsafe { &*s.face };
s.gc = face.gc;
s.set_stippled_p(face.stipple != 0);
match s.hl {
draw_glyphs_face::DRAW_NORMAL_TEXT
| draw_glyphs_face::DRAW_INVERSE_VIDEO
| draw_glyphs_face::DRAW_MOUSE_FACE
| draw_glyphs_face::DRAW_IMAGE_RAISED
| draw_glyphs_face::DRAW_IMAGE_SUNKEN => {
let face = unsafe { &*s.face };
s.gc = face.gc;
s.set_stippled_p(face.stipple != 0);
}

draw_glyphs_face::DRAW_CURSOR => {
let face = unsafe { &*s.face };
let output: OutputRef = unsafe { (*s.f).output_data.wr.into() };
let dpyinfo: DisplayInfoRef = output.output.display_info.into();

let mut foreground = face.background;
let mut background = color_to_pixel(output.cursor_color);

// If the glyph would be invisible, try a different foreground.
if foreground == background {
foreground = face.foreground;
}

if foreground == background {
foreground = color_to_pixel(output.cursor_foreground_color);
}

if foreground == background {
foreground = face.foreground;
}

// Make sure the cursor is distinct from text in this face.
if foreground == face.foreground && background == face.background {
foreground = face.background;
background = face.foreground;
}

let gc = &mut dpyinfo.get_inner().scratch_cursor_gc;
gc.foreground = foreground;
gc.background = background;
s.gc = gc.as_mut();

s.set_stippled_p(false);
}

_ => panic!("invalid draw_glyphs_face"),
}

let type_ = s.first_glyph().type_();

Expand Down Expand Up @@ -346,4 +397,50 @@ impl DrawCanvas {
);
});
}

pub fn draw_hollow_box_cursor(&mut self, x: i32, y: i32, width: i32, height: i32) {
let cursor_color = self.output.cursor_color;

let border_widths = LayoutSideOffsets::new_all_same(1.0);

let border_side = BorderSide {
color: cursor_color,
style: BorderStyle::Solid,
};

let border_details = BorderDetails::Normal(NormalBorder {
top: border_side,
right: border_side,
bottom: border_side,
left: border_side,
radius: BorderRadius::uniform(0.0),
do_aa: true,
});

let bounds = (x, y).by(width, height);

self.output.display(|builder, space_and_clip| {
builder.push_border(
&CommonItemProperties::new(bounds, space_and_clip),
bounds,
border_widths,
border_details,
);
});
}

pub fn draw_bar_cursor(&mut self, face: &face, x: i32, y: i32, width: i32, height: i32) {
let cursor_color = if pixel_to_color(face.background) == self.output.cursor_color {
pixel_to_color(face.foreground)
} else {
self.output.cursor_color
};

self.output.display(|builder, space_and_clip| {
builder.push_rect(
&CommonItemProperties::new((x, y).by(width, height), space_and_clip),
cursor_color,
);
});
}
}
1 change: 1 addition & 0 deletions rust_src/src/webrender_backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod keyboard;
pub mod output;
pub mod term;

mod cursor;
mod draw_canvas;
mod glyph;
mod texture;
4 changes: 4 additions & 0 deletions rust_src/src/webrender_backend/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub struct Output {
pub display_list_builder: Option<DisplayListBuilder>,

pub background_color: ColorF,
pub cursor_color: ColorF,
pub cursor_foreground_color: ColorF,

window: Window,

Expand Down Expand Up @@ -84,6 +86,8 @@ impl Output {
document_id,
display_list_builder: None,
background_color: ColorF::WHITE,
cursor_color: ColorF::BLACK,
cursor_foreground_color: ColorF::WHITE,
window,
event_loop_proxy,
color_bits,
Expand Down
Loading

0 comments on commit e768f96

Please sign in to comment.