tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

multiwindow.rs (10232B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 extern crate euclid;
      6 extern crate gleam;
      7 extern crate glutin;
      8 extern crate webrender;
      9 extern crate winit;
     10 
     11 use gleam::gl;
     12 use glutin::NotCurrent;
     13 use std::fs::File;
     14 use std::io::Read;
     15 use webrender::api::*;
     16 use webrender::api::units::*;
     17 use webrender::render_api::*;
     18 use webrender::DebugFlags;
     19 use winit::dpi::LogicalSize;
     20 use winit::platform::run_return::EventLoopExtRunReturn;
     21 
     22 struct Notifier {
     23    events_proxy: winit::event_loop::EventLoopProxy<()>,
     24 }
     25 
     26 impl Notifier {
     27    fn new(events_proxy: winit::event_loop::EventLoopProxy<()>) -> Notifier {
     28        Notifier { events_proxy }
     29    }
     30 }
     31 
     32 impl RenderNotifier for Notifier {
     33    fn clone(&self) -> Box<dyn RenderNotifier> {
     34        Box::new(Notifier {
     35            events_proxy: self.events_proxy.clone(),
     36        })
     37    }
     38 
     39    fn wake_up(&self, _composite_needed: bool) {
     40        #[cfg(not(target_os = "android"))]
     41        let _ = self.events_proxy.send_event(());
     42    }
     43 
     44    fn new_frame_ready(&self,
     45                       _: DocumentId,
     46                       _: FramePublishId,
     47                       params: &FrameReadyParams) {
     48        self.wake_up(params.render);
     49    }
     50 }
     51 
     52 struct Window {
     53    events_loop: winit::event_loop::EventLoop<()>, //TODO: share events loop?
     54    context: Option<glutin::WindowedContext<NotCurrent>>,
     55    renderer: webrender::Renderer,
     56    name: &'static str,
     57    pipeline_id: PipelineId,
     58    document_id: DocumentId,
     59    epoch: Epoch,
     60    api: RenderApi,
     61    font_instance_key: FontInstanceKey,
     62 }
     63 
     64 impl Window {
     65    fn new(name: &'static str, clear_color: ColorF) -> Self {
     66        let events_loop = winit::event_loop::EventLoop::new();
     67        let window_builder = winit::window::WindowBuilder::new()
     68            .with_title(name)
     69            .with_inner_size(LogicalSize::new(800. as f64, 600. as f64));
     70        let context = glutin::ContextBuilder::new()
     71            .with_gl(glutin::GlRequest::GlThenGles {
     72                opengl_version: (3, 2),
     73                opengles_version: (3, 0),
     74            })
     75            .build_windowed(window_builder, &events_loop)
     76            .unwrap();
     77 
     78        let context = unsafe { context.make_current().unwrap() };
     79 
     80        let gl = match context.get_api() {
     81            glutin::Api::OpenGl => unsafe {
     82                gl::GlFns::load_with(|symbol| context.get_proc_address(symbol) as *const _)
     83            },
     84            glutin::Api::OpenGlEs => unsafe {
     85                gl::GlesFns::load_with(|symbol| context.get_proc_address(symbol) as *const _)
     86            },
     87            glutin::Api::WebGl => unimplemented!(),
     88        };
     89 
     90        let opts = webrender::WebRenderOptions {
     91            clear_color,
     92            ..webrender::WebRenderOptions::default()
     93        };
     94 
     95        let device_size = {
     96            let size = context
     97                .window()
     98                .inner_size();
     99            DeviceIntSize::new(size.width as i32, size.height as i32)
    100        };
    101        let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
    102        let (renderer, sender) = webrender::create_webrender_instance(gl.clone(), notifier, opts, None).unwrap();
    103        let mut api = sender.create_api();
    104        let document_id = api.add_document(device_size);
    105 
    106        let epoch = Epoch(0);
    107        let pipeline_id = PipelineId(0, 0);
    108        let mut txn = Transaction::new();
    109 
    110        let font_key = api.generate_font_key();
    111        let font_bytes = load_file("../wrench/reftests/text/FreeSans.ttf");
    112        txn.add_raw_font(font_key, font_bytes, 0);
    113 
    114        let font_instance_key = api.generate_font_instance_key();
    115        txn.add_font_instance(font_instance_key, font_key, 32.0, None, None, Vec::new());
    116 
    117        api.send_transaction(document_id, txn);
    118 
    119        Window {
    120            events_loop,
    121            context: Some(unsafe { context.make_not_current().unwrap() }),
    122            renderer,
    123            name,
    124            epoch,
    125            pipeline_id,
    126            document_id,
    127            api,
    128            font_instance_key,
    129        }
    130    }
    131 
    132    fn tick(&mut self) -> bool {
    133        let mut do_exit = false;
    134        let my_name = &self.name;
    135        let renderer = &mut self.renderer;
    136        let api = &mut self.api;
    137 
    138        self.events_loop.run_return(|global_event, _elwt, control_flow| {
    139            *control_flow = winit::event_loop::ControlFlow::Exit;
    140            match global_event {
    141                winit::event::Event::WindowEvent { event, .. } => match event {
    142                    winit::event::WindowEvent::CloseRequested |
    143                    winit::event::WindowEvent::KeyboardInput {
    144                        input: winit::event::KeyboardInput {
    145                            virtual_keycode: Some(winit::event::VirtualKeyCode::Escape),
    146                            ..
    147                        },
    148                        ..
    149                    } => {
    150                        do_exit = true
    151                    }
    152                    winit::event::WindowEvent::KeyboardInput {
    153                        input: winit::event::KeyboardInput {
    154                            state: winit::event::ElementState::Pressed,
    155                            virtual_keycode: Some(winit::event::VirtualKeyCode::P),
    156                            ..
    157                        },
    158                        ..
    159                    } => {
    160                        println!("set flags {}", my_name);
    161                        api.send_debug_cmd(DebugCommand::SetFlags(DebugFlags::PROFILER_DBG))
    162                    }
    163                    _ => {}
    164                }
    165                _ => {}
    166            }
    167        });
    168        if do_exit {
    169            return true
    170        }
    171 
    172        let context = unsafe { self.context.take().unwrap().make_current().unwrap() };
    173        let device_pixel_ratio = context.window().scale_factor() as f32;
    174        let device_size = {
    175            let size = context
    176                .window()
    177                .inner_size();
    178            DeviceIntSize::new(size.width as i32, size.height as i32)
    179        };
    180        let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
    181        let mut txn = Transaction::new();
    182        let mut builder = DisplayListBuilder::new(self.pipeline_id);
    183        let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
    184        builder.begin();
    185 
    186        let bounds = LayoutRect::from_size(layout_size);
    187        builder.push_simple_stacking_context(
    188            bounds.min,
    189            space_and_clip.spatial_id,
    190            PrimitiveFlags::IS_BACKFACE_VISIBLE,
    191        );
    192 
    193        builder.push_rect(
    194            &CommonItemProperties::new(
    195                LayoutRect::from_origin_and_size(
    196                    LayoutPoint::new(100.0, 200.0),
    197                    LayoutSize::new(100.0, 200.0),
    198                ),
    199                space_and_clip,
    200            ),
    201            LayoutRect::from_origin_and_size(
    202                LayoutPoint::new(100.0, 200.0),
    203                LayoutSize::new(100.0, 200.0),
    204            ),
    205            ColorF::new(0.0, 1.0, 0.0, 1.0));
    206 
    207        let text_bounds = LayoutRect::from_origin_and_size(
    208            LayoutPoint::new(100.0, 50.0),
    209            LayoutSize::new(700.0, 200.0)
    210        );
    211        let glyphs = vec![
    212            GlyphInstance {
    213                index: 48,
    214                point: LayoutPoint::new(100.0, 100.0),
    215            },
    216            GlyphInstance {
    217                index: 68,
    218                point: LayoutPoint::new(150.0, 100.0),
    219            },
    220            GlyphInstance {
    221                index: 80,
    222                point: LayoutPoint::new(200.0, 100.0),
    223            },
    224            GlyphInstance {
    225                index: 82,
    226                point: LayoutPoint::new(250.0, 100.0),
    227            },
    228            GlyphInstance {
    229                index: 81,
    230                point: LayoutPoint::new(300.0, 100.0),
    231            },
    232            GlyphInstance {
    233                index: 3,
    234                point: LayoutPoint::new(350.0, 100.0),
    235            },
    236            GlyphInstance {
    237                index: 86,
    238                point: LayoutPoint::new(400.0, 100.0),
    239            },
    240            GlyphInstance {
    241                index: 79,
    242                point: LayoutPoint::new(450.0, 100.0),
    243            },
    244            GlyphInstance {
    245                index: 72,
    246                point: LayoutPoint::new(500.0, 100.0),
    247            },
    248            GlyphInstance {
    249                index: 83,
    250                point: LayoutPoint::new(550.0, 100.0),
    251            },
    252            GlyphInstance {
    253                index: 87,
    254                point: LayoutPoint::new(600.0, 100.0),
    255            },
    256            GlyphInstance {
    257                index: 17,
    258                point: LayoutPoint::new(650.0, 100.0),
    259            },
    260        ];
    261 
    262        builder.push_text(
    263            &CommonItemProperties::new(
    264                text_bounds,
    265                space_and_clip,
    266            ),
    267            text_bounds,
    268            &glyphs,
    269            self.font_instance_key,
    270            ColorF::new(1.0, 1.0, 0.0, 1.0),
    271            None,
    272        );
    273 
    274        builder.pop_stacking_context();
    275 
    276        txn.set_display_list(
    277            self.epoch,
    278            builder.end(),
    279        );
    280        txn.set_root_pipeline(self.pipeline_id);
    281        txn.generate_frame(0, true, false, RenderReasons::empty());
    282        api.send_transaction(self.document_id, txn);
    283 
    284        renderer.update();
    285        renderer.render(device_size, 0).unwrap();
    286        context.swap_buffers().ok();
    287 
    288        self.context = Some(unsafe { context.make_not_current().unwrap() });
    289 
    290        false
    291    }
    292 
    293    fn deinit(self) {
    294        self.renderer.deinit();
    295    }
    296 }
    297 
    298 fn main() {
    299    let mut win1 = Window::new("window1", ColorF::new(0.3, 0.0, 0.0, 1.0));
    300    let mut win2 = Window::new("window2", ColorF::new(0.0, 0.3, 0.0, 1.0));
    301 
    302    loop {
    303        if win1.tick() {
    304            break;
    305        }
    306        if win2.tick() {
    307            break;
    308        }
    309    }
    310 
    311    win1.deinit();
    312    win2.deinit();
    313 }
    314 
    315 fn load_file(name: &str) -> Vec<u8> {
    316    let mut file = File::open(name).unwrap();
    317    let mut buffer = vec![];
    318    file.read_to_end(&mut buffer).unwrap();
    319    buffer
    320 }