mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00: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::io::Write;
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_void;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -56,13 +57,22 @@ pub enum MLLogLevel {
|
|||
#[repr(transparent)]
|
||||
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;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn init_servo(ctxt: EGLContext,
|
||||
surf: EGLSurface,
|
||||
disp: EGLDisplay,
|
||||
app: MLApp,
|
||||
logger: MLLogger,
|
||||
history_update: MLHistoryUpdate,
|
||||
url: *const c_char,
|
||||
width: u32,
|
||||
height: u32,
|
||||
|
@ -100,7 +110,9 @@ pub unsafe extern "C" fn init_servo(ctxt: EGLContext,
|
|||
]);
|
||||
|
||||
let result = Box::new(ServoInstance {
|
||||
app: app,
|
||||
browser_id: browser_id,
|
||||
history_update: history_update,
|
||||
servo: servo,
|
||||
});
|
||||
Box::into_raw(result)
|
||||
|
@ -130,10 +142,19 @@ pub unsafe extern "C" fn heartbeat_servo(servo: *mut ServoInstance) {
|
|||
EmbedderMsg::AllowOpeningBrowser(sender) => {
|
||||
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
|
||||
EmbedderMsg::ChangePageTitle(..) |
|
||||
EmbedderMsg::BrowserCreated(..) |
|
||||
EmbedderMsg::HistoryChanged(..) |
|
||||
EmbedderMsg::LoadStart |
|
||||
EmbedderMsg::LoadComplete |
|
||||
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]
|
||||
pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) {
|
||||
// Servo drop goes here!
|
||||
|
@ -193,7 +230,9 @@ pub unsafe extern "C" fn discard_servo(servo: *mut ServoInstance) {
|
|||
}
|
||||
|
||||
pub struct ServoInstance {
|
||||
app: MLApp,
|
||||
browser_id: BrowserId,
|
||||
history_update: MLHistoryUpdate,
|
||||
servo: Servo<WindowInstance>,
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include <lumin/event/ControlTouchPadInputEventData.h>
|
||||
#include <lumin/node/QuadNode.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>
|
||||
|
||||
typedef struct Opaque ServoInstance;
|
||||
|
@ -48,6 +51,11 @@ public:
|
|||
*/
|
||||
Servo2D& operator=(Servo2D&&) = delete;
|
||||
|
||||
/**
|
||||
* Update the browser history UI
|
||||
*/
|
||||
void updateHistory(bool canGoBack, const char* url, bool canGoForward);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the Landscape Application.
|
||||
|
@ -93,6 +101,7 @@ protected:
|
|||
virtual bool eventListener(lumin::ServerEvent* event) override;
|
||||
bool touchpadEventListener(lumin::ControlTouchPadInputEventData* event);
|
||||
bool keyEventListener(lumin::KeyInputEventData* event);
|
||||
void urlBarEventListener();
|
||||
|
||||
/**
|
||||
* 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::PlanarResource* plane_ = nullptr; // the plane we're rendering into
|
||||
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
|
||||
};
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <lumin/node/RootNode.h>
|
||||
#include <lumin/node/QuadNode.h>
|
||||
#include <lumin/ui/Cursor.h>
|
||||
#include <lumin/ui/node/UiButton.h>
|
||||
#include <ml_logging.h>
|
||||
#include <scenesGen.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.
|
||||
// For the moment, this doesn't handle input events.
|
||||
extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, MLLogger,
|
||||
const char* url, int width, int height, float hidpi);
|
||||
extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay,
|
||||
Servo2D*, MLLogger, MLHistoryUpdate,
|
||||
const char* url, int width, int height, float hidpi);
|
||||
extern "C" void heartbeat_servo(ServoInstance*);
|
||||
extern "C" void cursor_servo(ServoInstance*, float x, float y, bool triggered);
|
||||
extern "C" void traverse_servo(ServoInstance*, int delta);
|
||||
extern "C" void navigate_servo(ServoInstance*, const char* text);
|
||||
extern "C" void discard_servo(ServoInstance*);
|
||||
|
||||
// Create a Servo2D instance
|
||||
|
@ -120,7 +126,7 @@ int Servo2D::init() {
|
|||
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
|
||||
// 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_) {
|
||||
ML_LOG(Error, "Servo2D Failed to init servo instance");
|
||||
abort();
|
||||
|
@ -129,24 +135,33 @@ int Servo2D::init() {
|
|||
|
||||
// Add a callback to the back button
|
||||
std::string back_button_id = Servo2D_exportedNodes::backButton;
|
||||
lumin::ui::UiButton* back_button = lumin::ui::UiButton::CastFrom(prism_->findNode(back_button_id, root_node));
|
||||
if (!back_button) {
|
||||
back_button_ = lumin::ui::UiButton::CastFrom(prism_->findNode(back_button_id, root_node));
|
||||
if (!back_button_) {
|
||||
ML_LOG(Error, "Servo2D Failed to get back button");
|
||||
abort();
|
||||
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
|
||||
std::string fwd_button_id = Servo2D_exportedNodes::fwdButton;
|
||||
lumin::ui::UiButton* fwd_button = lumin::ui::UiButton::CastFrom(prism_->findNode(fwd_button_id, root_node));
|
||||
if (!fwd_button) {
|
||||
fwd_button_ = lumin::ui::UiButton::CastFrom(prism_->findNode(fwd_button_id, root_node));
|
||||
if (!fwd_button_) {
|
||||
ML_LOG(Error, "Servo2D Failed to get forward button");
|
||||
abort();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -268,3 +283,13 @@ bool Servo2D::keyEventListener(lumin::KeyInputEventData* event) {
|
|||
cursor_servo(servo_, pos.x, pos.y, 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