mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Get the Servo2D URL bar to show the current URL, and to navigate when edited.
This commit is contained in:
parent
4c5a3c0d9f
commit
c2f33709d1
3 changed files with 88 additions and 12 deletions
|
@ -40,6 +40,7 @@ use std::ffi::CStr;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
use std::os::raw::c_void;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -56,13 +57,22 @@ pub enum MLLogLevel {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct MLLogger(extern "C" fn (MLLogLevel, *const c_char));
|
pub struct MLLogger(extern "C" fn (MLLogLevel, *const c_char));
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct MLHistoryUpdate(extern "C" fn (MLApp, bool, *const c_char, bool));
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct MLApp(*mut c_void);
|
||||||
|
|
||||||
const LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info;
|
const LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn init_servo(ctxt: EGLContext,
|
pub unsafe extern "C" fn init_servo(ctxt: EGLContext,
|
||||||
surf: EGLSurface,
|
surf: EGLSurface,
|
||||||
disp: EGLDisplay,
|
disp: EGLDisplay,
|
||||||
|
app: MLApp,
|
||||||
logger: MLLogger,
|
logger: MLLogger,
|
||||||
|
history_update: MLHistoryUpdate,
|
||||||
url: *const c_char,
|
url: *const c_char,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
@ -100,7 +110,9 @@ pub unsafe extern "C" fn init_servo(ctxt: EGLContext,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let result = Box::new(ServoInstance {
|
let result = Box::new(ServoInstance {
|
||||||
|
app: app,
|
||||||
browser_id: browser_id,
|
browser_id: browser_id,
|
||||||
|
history_update: history_update,
|
||||||
servo: servo,
|
servo: servo,
|
||||||
});
|
});
|
||||||
Box::into_raw(result)
|
Box::into_raw(result)
|
||||||
|
@ -130,10 +142,19 @@ pub unsafe extern "C" fn heartbeat_servo(servo: *mut ServoInstance) {
|
||||||
EmbedderMsg::AllowOpeningBrowser(sender) => {
|
EmbedderMsg::AllowOpeningBrowser(sender) => {
|
||||||
let _ = sender.send(false);
|
let _ = sender.send(false);
|
||||||
},
|
},
|
||||||
|
// Update the history UI
|
||||||
|
EmbedderMsg::HistoryChanged(urls, index) => {
|
||||||
|
if let Some(url) = urls.get(index) {
|
||||||
|
if let Ok(cstr) = CString::new(url.as_str()) {
|
||||||
|
let can_go_back = index > 0;
|
||||||
|
let can_go_fwd = (index + 1) < urls.len();
|
||||||
|
(servo.history_update.0)(servo.app, can_go_back, cstr.as_ptr(), can_go_fwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
// Ignore most messages for now
|
// Ignore most messages for now
|
||||||
EmbedderMsg::ChangePageTitle(..) |
|
EmbedderMsg::ChangePageTitle(..) |
|
||||||
EmbedderMsg::BrowserCreated(..) |
|
EmbedderMsg::BrowserCreated(..) |
|
||||||
EmbedderMsg::HistoryChanged(..) |
|
|
||||||
EmbedderMsg::LoadStart |
|
EmbedderMsg::LoadStart |
|
||||||
EmbedderMsg::LoadComplete |
|
EmbedderMsg::LoadComplete |
|
||||||
EmbedderMsg::CloseBrowser |
|
EmbedderMsg::CloseBrowser |
|
||||||
|
@ -184,6 +205,22 @@ pub unsafe extern "C" fn traverse_servo(servo: *mut ServoInstance, delta: i32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn navigate_servo(servo: *mut ServoInstance, text: *const c_char) {
|
||||||
|
if let Some(servo) = servo.as_mut() {
|
||||||
|
let text = CStr::from_ptr(text).to_str().expect("Failed to convert text to UTF-8");
|
||||||
|
let url = ServoUrl::parse(text).unwrap_or_else(|_| {
|
||||||
|
let mut search = ServoUrl::parse("http://google.com/search")
|
||||||
|
.expect("Failed to parse search URL")
|
||||||
|
.into_url();
|
||||||
|
search.query_pairs_mut().append_pair("q", text);
|
||||||
|
ServoUrl::from_url(search)
|
||||||
|
});
|
||||||
|
let window_event = WindowEvent::LoadUrl(servo.browser_id, url);
|
||||||
|
servo.servo.handle_events(vec![window_event]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) {
|
pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) {
|
||||||
// Servo drop goes here!
|
// Servo drop goes here!
|
||||||
|
@ -193,7 +230,9 @@ pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ServoInstance {
|
pub struct ServoInstance {
|
||||||
|
app: MLApp,
|
||||||
browser_id: BrowserId,
|
browser_id: BrowserId,
|
||||||
|
history_update: MLHistoryUpdate,
|
||||||
servo: Servo<WindowInstance>,
|
servo: Servo<WindowInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
#include <lumin/event/ControlTouchPadInputEventData.h>
|
#include <lumin/event/ControlTouchPadInputEventData.h>
|
||||||
#include <lumin/node/QuadNode.h>
|
#include <lumin/node/QuadNode.h>
|
||||||
#include <lumin/resource/PlanarResource.h>
|
#include <lumin/resource/PlanarResource.h>
|
||||||
|
#include <lumin/ui/KeyboardDefines.h>
|
||||||
|
#include <lumin/ui/node/UiButton.h>
|
||||||
|
#include <lumin/ui/node/UiTextEdit.h>
|
||||||
#include <SceneDescriptor.h>
|
#include <SceneDescriptor.h>
|
||||||
|
|
||||||
typedef struct Opaque ServoInstance;
|
typedef struct Opaque ServoInstance;
|
||||||
|
@ -48,6 +51,11 @@ public:
|
||||||
*/
|
*/
|
||||||
Servo2D& operator=(Servo2D&&) = delete;
|
Servo2D& operator=(Servo2D&&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the browser history UI
|
||||||
|
*/
|
||||||
|
void updateHistory(bool canGoBack, const char* url, bool canGoForward);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Initializes the Landscape Application.
|
* Initializes the Landscape Application.
|
||||||
|
@ -93,6 +101,7 @@ protected:
|
||||||
virtual bool eventListener(lumin::ServerEvent* event) override;
|
virtual bool eventListener(lumin::ServerEvent* event) override;
|
||||||
bool touchpadEventListener(lumin::ControlTouchPadInputEventData* event);
|
bool touchpadEventListener(lumin::ControlTouchPadInputEventData* event);
|
||||||
bool keyEventListener(lumin::KeyInputEventData* event);
|
bool keyEventListener(lumin::KeyInputEventData* event);
|
||||||
|
void urlBarEventListener();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current cursor position, with respect to the viewport.
|
* Get the current cursor position, with respect to the viewport.
|
||||||
|
@ -104,5 +113,8 @@ private:
|
||||||
lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders.
|
lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders.
|
||||||
lumin::PlanarResource* plane_ = nullptr; // the plane we're rendering into
|
lumin::PlanarResource* plane_ = nullptr; // the plane we're rendering into
|
||||||
lumin::QuadNode* content_node_ = nullptr; // the node containing the plane
|
lumin::QuadNode* content_node_ = nullptr; // the node containing the plane
|
||||||
|
lumin::ui::UiButton* back_button_ = nullptr; // the back button
|
||||||
|
lumin::ui::UiButton* fwd_button_ = nullptr; // the forward button
|
||||||
|
lumin::ui::UiTextEdit* url_bar_ = nullptr; // the URL bar
|
||||||
ServoInstance* servo_ = nullptr; // the servo instance we're embedding
|
ServoInstance* servo_ = nullptr; // the servo instance we're embedding
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <lumin/node/RootNode.h>
|
#include <lumin/node/RootNode.h>
|
||||||
#include <lumin/node/QuadNode.h>
|
#include <lumin/node/QuadNode.h>
|
||||||
#include <lumin/ui/Cursor.h>
|
#include <lumin/ui/Cursor.h>
|
||||||
#include <lumin/ui/node/UiButton.h>
|
|
||||||
#include <ml_logging.h>
|
#include <ml_logging.h>
|
||||||
#include <scenesGen.h>
|
#include <scenesGen.h>
|
||||||
#include <SceneDescriptor.h>
|
#include <SceneDescriptor.h>
|
||||||
|
@ -35,13 +34,20 @@ void logger(MLLogLevel lvl, char* msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A function which updates the history ui, suitable for passing into Servo
|
||||||
|
typedef void (*MLHistoryUpdate)(Servo2D* app, bool canGoBack, char* url, bool canGoForward);
|
||||||
|
void history(Servo2D* app, bool canGoBack, char* url, bool canGoForward) {
|
||||||
|
app->updateHistory(canGoBack, url, canGoForward);
|
||||||
|
}
|
||||||
|
|
||||||
// The functions Servo provides for hooking up to the ML.
|
// The functions Servo provides for hooking up to the ML.
|
||||||
// For the moment, this doesn't handle input events.
|
extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay,
|
||||||
extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, MLLogger,
|
Servo2D*, MLLogger, MLHistoryUpdate,
|
||||||
const char* url, int width, int height, float hidpi);
|
const char* url, int width, int height, float hidpi);
|
||||||
extern "C" void heartbeat_servo(ServoInstance*);
|
extern "C" void heartbeat_servo(ServoInstance*);
|
||||||
extern "C" void cursor_servo(ServoInstance*, float x, float y, bool triggered);
|
extern "C" void cursor_servo(ServoInstance*, float x, float y, bool triggered);
|
||||||
extern "C" void traverse_servo(ServoInstance*, int delta);
|
extern "C" void traverse_servo(ServoInstance*, int delta);
|
||||||
|
extern "C" void navigate_servo(ServoInstance*, const char* text);
|
||||||
extern "C" void discard_servo(ServoInstance*);
|
extern "C" void discard_servo(ServoInstance*);
|
||||||
|
|
||||||
// Create a Servo2D instance
|
// Create a Servo2D instance
|
||||||
|
@ -120,7 +126,7 @@ int Servo2D::init() {
|
||||||
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
|
||||||
// Hook into servo
|
// Hook into servo
|
||||||
servo_ = init_servo(ctx, surf, dpy, logger, "https://servo.org/", VIEWPORT_H, VIEWPORT_W, HIDPI);
|
servo_ = init_servo(ctx, surf, dpy, this, logger, history, "https://servo.org/", VIEWPORT_H, VIEWPORT_W, HIDPI);
|
||||||
if (!servo_) {
|
if (!servo_) {
|
||||||
ML_LOG(Error, "Servo2D Failed to init servo instance");
|
ML_LOG(Error, "Servo2D Failed to init servo instance");
|
||||||
abort();
|
abort();
|
||||||
|
@ -129,24 +135,33 @@ int Servo2D::init() {
|
||||||
|
|
||||||
// Add a callback to the back button
|
// Add a callback to the back button
|
||||||
std::string back_button_id = Servo2D_exportedNodes::backButton;
|
std::string back_button_id = Servo2D_exportedNodes::backButton;
|
||||||
lumin::ui::UiButton* back_button = lumin::ui::UiButton::CastFrom(prism_->findNode(back_button_id, root_node));
|
back_button_ = lumin::ui::UiButton::CastFrom(prism_->findNode(back_button_id, root_node));
|
||||||
if (!back_button) {
|
if (!back_button_) {
|
||||||
ML_LOG(Error, "Servo2D Failed to get back button");
|
ML_LOG(Error, "Servo2D Failed to get back button");
|
||||||
abort();
|
abort();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
back_button->onActivateSub(std::bind(traverse_servo, servo_, -1));
|
back_button_->onActivateSub(std::bind(traverse_servo, servo_, -1));
|
||||||
|
|
||||||
// Add a callback to the forward button
|
// Add a callback to the forward button
|
||||||
std::string fwd_button_id = Servo2D_exportedNodes::fwdButton;
|
std::string fwd_button_id = Servo2D_exportedNodes::fwdButton;
|
||||||
lumin::ui::UiButton* fwd_button = lumin::ui::UiButton::CastFrom(prism_->findNode(fwd_button_id, root_node));
|
fwd_button_ = lumin::ui::UiButton::CastFrom(prism_->findNode(fwd_button_id, root_node));
|
||||||
if (!fwd_button) {
|
if (!fwd_button_) {
|
||||||
ML_LOG(Error, "Servo2D Failed to get forward button");
|
ML_LOG(Error, "Servo2D Failed to get forward button");
|
||||||
abort();
|
abort();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fwd_button->onActivateSub(std::bind(traverse_servo, servo_, +1));
|
fwd_button_->onActivateSub(std::bind(traverse_servo, servo_, +1));
|
||||||
|
|
||||||
|
// Add a callback to the URL bar
|
||||||
|
std::string url_bar_id = Servo2D_exportedNodes::urlBar;
|
||||||
|
url_bar_ = lumin::ui::UiTextEdit::CastFrom(prism_->findNode(url_bar_id, root_node));
|
||||||
|
if (!url_bar_) {
|
||||||
|
ML_LOG(Error, "Servo2D Failed to get URL bar");
|
||||||
|
abort();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
url_bar_->onFocusLostSub(std::bind(&Servo2D::urlBarEventListener, this));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,3 +283,13 @@ bool Servo2D::keyEventListener(lumin::KeyInputEventData* event) {
|
||||||
cursor_servo(servo_, pos.x, pos.y, true);
|
cursor_servo(servo_, pos.x, pos.y, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Servo2D::urlBarEventListener() {
|
||||||
|
navigate_servo(servo_, url_bar_->getText().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Servo2D::updateHistory(bool canGoBack, const char* url, bool canGoForward) {
|
||||||
|
back_button_->setEnabled(canGoBack);
|
||||||
|
fwd_button_->setEnabled(canGoForward);
|
||||||
|
url_bar_->setText(url);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue