Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/bc546388ce428be5cfa37cecb174d549c7b30320
...commit
http://git.netsurf-browser.org/netsurf.git/commit/bc546388ce428be5cfa37cecb174d549c7b30320
...tree
http://git.netsurf-browser.org/netsurf.git/tree/bc546388ce428be5cfa37cecb174d549c7b30320
The branch, vince/fltk has been updated
discards 04900e82e65f8669675538a66a01b56a3e473cb2 (commit)
via bc546388ce428be5cfa37cecb174d549c7b30320 (commit)
via 28ecbf82ed3024f51be4c87928fd91bacfc15cbc (commit)
via 847d5680613cb578ba4a548960480363a3230174 (commit)
via 5749ace60f9359b6bc31d7f8c071d87d270733da (commit)
via 6faa70893b70fc43d6f398f2e43719c763c2d193 (commit)
via a11ad57bf64ae4e701e049ced1233cc4c7b22054 (commit)
via 9a7e41d3ea966387eff8abd86198812244cd47bc (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (04900e82e65f8669675538a66a01b56a3e473cb2)
\
N -- N -- N (bc546388ce428be5cfa37cecb174d549c7b30320)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=bc546388ce428be5cfa37cecb174d549c7b30320
commit bc546388ce428be5cfa37cecb174d549c7b30320
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
greatly improve fltk browser user interface
diff --git a/frontends/fltk/window.cpp b/frontends/fltk/window.cpp
index 19aa265..fffc380 100644
--- a/frontends/fltk/window.cpp
+++ b/frontends/fltk/window.cpp
@@ -24,11 +24,17 @@
#include <stddef.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Scrollbar.H>
#include <FL/fl_draw.H>
+#include <Fl/Fl_Output.H>
+#include <Fl/Fl_Pack.H>
+#include <Fl/Fl_Button.H>
extern "C" {
#include "utils/errors.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
#include "netsurf/types.h"
#include "netsurf/mouse.h"
#include "netsurf/window.h"
@@ -36,6 +42,7 @@ extern "C" {
#include "netsurf/content.h"
#include "netsurf/browser_window.h"
#include "netsurf/mouse.h"
+#include "desktop/browser_history.h"
}
@@ -44,10 +51,16 @@ extern "C" {
extern bool nsfltk_done;
+struct gui_window {
+ class NS_Window *window;
+};
+
class NS_Widget : public Fl_Widget
{
private:
- struct browser_window *mbw;
+ struct browser_window *m_bw;
+ int m_xoffset;
+ int m_yoffset;
protected:
void draw();
@@ -55,38 +68,19 @@ protected:
public:
NS_Widget(int X,int Y,int W,int H, struct browser_window *bw)
- : Fl_Widget(X,Y,W,H), mbw(bw) {}
-};
-
-
-class NS_Window : public Fl_Double_Window
-{
-private:
- struct browser_window *mbw;
- NS_Widget *mnswidget;
-
- void close_callback(Fl_Widget *w);
- static void static_close_callback(Fl_Widget *w, void *f) { ((NS_Window
*)f)->close_callback(w); }
+ : Fl_Widget(X,Y,W,H), m_bw(bw), m_xoffset(0), m_yoffset(0) {}
-public:
- NS_Window(int W, int H, struct browser_window *bw)
- : Fl_Double_Window(W,H), mbw(bw) {
- this->callback(static_close_callback, (void *)this);
- mnswidget = new NS_Widget(0, 0, W, H, bw);
- this->end();
- }
- ~NS_Window() { nsfltk_done=true; }
+ bool get_scroll(int *sx, int *sy);
+ nserror get_dimensions(int *width, int *height);
- NS_Widget *get_nswidget() { return mnswidget; }
+ nserror invalidate(const struct rect *rect);
+ void vscroll_callback(Fl_Scrollbar *w);
+ void hscroll_callback(Fl_Scrollbar *w);
};
-struct gui_window {
- struct browser_window *bw;
- NS_Window *window;
-};
/**
- * method to handle events on the netsurf browsing widget
+ * handle events on the netsurf browsing widget
*/
int NS_Widget::handle(int event)
{
@@ -99,10 +93,10 @@ int NS_Widget::handle(int event)
if (button == FL_LEFT_MOUSE) {
state |= BROWSER_MOUSE_PRESS_1;
}
- browser_window_mouse_click(mbw,
+ browser_window_mouse_click(m_bw,
(browser_mouse_state)state,
- Fl::event_x() - x(),
- Fl::event_y() - y());
+ Fl::event_x() - x() + m_xoffset,
+ Fl::event_y() - y() + m_yoffset);
return 1;
case FL_RELEASE:
@@ -111,10 +105,10 @@ int NS_Widget::handle(int event)
state |= BROWSER_MOUSE_CLICK_1;
}
- browser_window_mouse_click(mbw,
+ browser_window_mouse_click(m_bw,
(browser_mouse_state)state,
- Fl::event_x() - x(),
- Fl::event_y() - y());
+ Fl::event_x() - x() + m_xoffset,
+ Fl::event_y() - y() + m_yoffset);
return 1;
default:
@@ -124,7 +118,7 @@ int NS_Widget::handle(int event)
/**
- * method to redraw the netsurf browsing widget
+ * redraw the netsurf browsing widget
*/
void NS_Widget::draw()
{
@@ -140,103 +134,352 @@ void NS_Widget::draw()
.priv = NULL,
};
- browser_window_redraw(mbw, x(), y(), &clip, &ctx);
+ browser_window_redraw(m_bw,
+ x() - m_xoffset,
+ y() - m_yoffset,
+ &clip,
+ &ctx);
}
+
/**
- * callback when fltk window is closed
+ * vertical scrollbar position has been changed
*/
-void NS_Window::close_callback(Fl_Widget *w)
+void NS_Widget::vscroll_callback(Fl_Scrollbar *sb)
{
- browser_window_destroy(mbw);
+ m_yoffset = sb->value();
+ damage(FL_DAMAGE_SCROLL);
}
+
/**
- * Create and open a gui window for a browsing context.
- *
- * The implementing front end must create a context suitable
- * for it to display a window referred to as the "gui window".
- *
- * The frontend will be expected to request the core redraw
- * areas of the gui window which have become invalidated
- * either from toolkit expose events or as a result of a
- * invalidate() call.
- *
- * Most core operations used by the frontend concerning browser
- * windows require passing the browser window context therefor
- * the gui window must include a reference to the browser
- * window passed here.
- *
- * If GW_CREATE_CLONE flag is set existing is non-NULL.
- *
- * \param bw The core browsing context associated with the gui window
- * \param existing An existing gui_window, may be NULL.
- * \param flags flags to control the gui window creation.
- * \return gui window, or NULL on error.
+ * horizontal scrollbar position has been changed
*/
-static struct gui_window *
-nsfltk_window_create(struct browser_window *bw,
- struct gui_window *existing,
- gui_window_create_flags flags)
+void NS_Widget::hscroll_callback(Fl_Scrollbar *sb)
{
- struct gui_window *gw;
- gw = (struct gui_window *)calloc(1, sizeof(struct gui_window));
-
- gw->window = new NS_Window(800,600, bw);
+ m_xoffset = sb->value();
+ damage(FL_DAMAGE_SCROLL);
+}
- gw->window->show();
+/**
+ * get the current scroll offsets
+ */
+bool NS_Widget::get_scroll(int *sx, int *sy)
+{
+ *sx = m_xoffset;
+ *sy = m_yoffset;
- return gw;
+ return true;
}
+
/**
- * Destroy previously created gui window
- *
- * \param gw The gui window to destroy.
+ * get the viewable dimensions of browsing context
*/
-static void nsfltk_window_destroy(struct gui_window *gw)
+nserror NS_Widget::get_dimensions(int *width, int *height)
{
- Fl::delete_widget(gw->window);
- free(gw);
+ *width = w();
+ *height = h();
+
+ return NSERROR_OK;
}
/**
- * Invalidate an area of a window.
- *
- * The specified area of the window should now be considered
- * out of date. If the area is NULL the entire window must be
- * invalidated. It is expected that the windowing system will
- * then subsequently cause redraw/expose operations as
- * necessary.
- *
- * \note the frontend should not attempt to actually start the
- * redraw operations as a result of this callback because the
- * core redraw functions may already be threaded.
- *
- * \param gw The gui window to invalidate.
- * \param rect area to redraw or NULL for the entire window area
- * \return NSERROR_OK on success or appropriate error code
+ * mark an area of the browsing context as invalid
*/
-static nserror
-nsfltk_window_invalidate(struct gui_window *gw, const struct rect *rect)
+nserror NS_Widget::invalidate(const struct rect *rect)
{
- NS_Widget *nswidget;
- nswidget = gw->window->get_nswidget();
-
if (rect == NULL) {
- nswidget->damage(FL_DAMAGE_ALL);
+ damage(FL_DAMAGE_ALL);
+ } else {
+ damage(FL_DAMAGE_ALL,
+ rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+ return NSERROR_OK;
+
+}
+
+/**
+ * widget representing url bar
+ */
+class NS_URLBar : public Fl_Pack
+{
+private:
+ struct browser_window *m_bw;
+ Fl_Button *m_back_button;
+ Fl_Button *m_forward_button;
+ Fl_Input *m_input;
+
+ void back_callback(Fl_Button *button);
+ void forward_callback(Fl_Button *button);
+public:
+ NS_URLBar(int X,int Y,int W,int H, struct browser_window *bw);
+ nserror set_url(struct nsurl *url);
+
+ /* static wrapper for fltk callbacks */
+ static void static_back_callback(Fl_Widget *w, void *f);
+ static void static_forward_callback(Fl_Widget *w, void *f);
+
+};
+
+NS_URLBar::NS_URLBar(int X,int Y,int W,int H, struct browser_window *bw)
+ : Fl_Pack(X,Y,W,H), m_bw(bw)
+{
+ type(Fl_Pack::HORIZONTAL);
+ spacing(4);
+
+ m_back_button = new Fl_Button(0,0,H,H, "B");
+ m_back_button->callback(static_back_callback, (void *)this);
+
+ m_forward_button = new Fl_Button(0,0,H,H, "F");
+ m_forward_button->callback(static_forward_callback, (void *)this);
+
+ m_input = new Fl_Input(0,0,W,H);
+
+ end();
+
+ resizable(m_input);
+}
+
+nserror NS_URLBar::set_url(struct nsurl *url)
+{
+ size_t idn_url_l;
+ char *idn_url_s = NULL;
+ if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) == NSERROR_OK) {
+ m_input->value(idn_url_s, idn_url_l-1);
+ free(idn_url_s);
} else {
- nswidget->damage(FL_DAMAGE_ALL,
- rect->x0,
- rect->y0,
- rect->x1 - rect->x0,
- rect->y1 - rect->y0);
+ m_input->value(nsurl_access(url));
}
return NSERROR_OK;
}
+void NS_URLBar::back_callback(Fl_Button *button)
+{
+ browser_window_history_back(m_bw, false);
+}
+
+void NS_URLBar::forward_callback(Fl_Button *button)
+{
+ browser_window_history_forward(m_bw, false);
+}
+
+
+void NS_URLBar::static_back_callback(Fl_Widget *w, void *f)
+{
+ ((NS_URLBar *)f)->back_callback((Fl_Button *)w);
+}
+
+void NS_URLBar::static_forward_callback(Fl_Widget *w, void *f)
+{
+ ((NS_URLBar *)f)->forward_callback((Fl_Button *)w);
+}
+
+
+/**
+ * Class for netsurf window
+ */
+class NS_Window : public Fl_Double_Window
+{
+private:
+ struct browser_window *m_bw;
+
+ NS_URLBar *m_nsurlbar;
+ NS_Widget *m_nswidget;
+ Fl_Scrollbar *m_vscrollbar;
+ Fl_Scrollbar *m_hscrollbar;
+ Fl_Output *m_status;
+
+ nserror set_scroll(const struct rect *rect);
+ void set_status(const char *text);
+ void set_title(const char *title);
+ nserror set_extent(int w, int h);
+
+ void close_callback(Fl_Widget *w);
+
+ /* static wrapper for fltk callbacks */
+ static void static_close_callback(Fl_Widget *w, void *f);
+ static void static_hscroll_callback(Fl_Widget *w, void *f);
+ static void static_vscroll_callback(Fl_Widget *w, void *f);
+
+public:
+ NS_Window(int W, int H, struct browser_window *bw);
+ ~NS_Window() { nsfltk_done=true; }
+
+ /* static wrappers to be able to call instance methods */
+ static nserror static_set_scroll(struct gui_window *gw, const struct
rect *rect);
+ static void static_set_status(struct gui_window *gw, const char *text);
+ static void static_set_title(struct gui_window *gw, const char *title);
+
+ static bool static_get_scroll(struct gui_window *gw, int *sx, int *sy);
+ static nserror static_set_url(struct gui_window *gw, struct nsurl *url);
+
+ static nserror static_event(struct gui_window *gw, enum
gui_window_event event);
+ static nserror static_invalidate(struct gui_window *gw, const struct
rect *rect);
+ static nserror static_get_dimensions(struct gui_window *gw, int *width,
int *height);
+ static struct gui_window *static_create(struct browser_window *bw,
struct gui_window *existing, gui_window_create_flags flags);
+ static void static_destroy(struct gui_window *gw);
+};
+
+
+/**
+ * netsurf window class constructor
+ */
+NS_Window::NS_Window(int W, int H, struct browser_window *bw)
+ : Fl_Double_Window(W,H), m_bw(bw)
+{
+ int scrlsize = Fl::scrollbar_size();
+ int splitx = (nsoption_int(toolbar_status_size) * W) / 10000;
+ int urlbarh = scrlsize * 2;
+
+ callback(static_close_callback, (void *)this);
+
+ // url bar
+ m_nsurlbar = new NS_URLBar(0, 0, W, urlbarh, bw);
+
+ // browser drawing canvas widget
+ m_nswidget = new NS_Widget(0,
+ m_nsurlbar->h(),
+ W - scrlsize,
+ H - scrlsize - urlbarh,
+ bw);
+
+ // vertical scrollbar
+ m_vscrollbar = new Fl_Scrollbar(m_nswidget->w(),
+ m_nsurlbar->h(),
+ scrlsize,
+ m_nswidget->h());
+ m_vscrollbar->callback(static_vscroll_callback, (void *)m_nswidget);
+ m_vscrollbar->value(0, m_nswidget->h(), 0, m_nswidget->h());
+
+ // horizontal scrollbar
+ m_hscrollbar = new Fl_Scrollbar(splitx,
+ m_nswidget->y() + m_nswidget->h(),
+ m_nswidget->w() - splitx,
+ scrlsize);
+ m_hscrollbar->type(FL_HORIZONTAL);
+ m_hscrollbar->callback(static_hscroll_callback, (void *)m_nswidget);
+ m_hscrollbar->value(0, m_nswidget->w(), 0, m_nswidget->w());
+
+ // status text
+ m_status = new Fl_Output(0, m_hscrollbar->y(), splitx, scrlsize);
+ end();
+
+ resizable(m_nswidget);
+}
+
+
+/**
+ * fltk window has been closed
+ */
+void NS_Window::close_callback(Fl_Widget *w)
+{
+ browser_window_destroy(m_bw);
+}
+
+
+
+
+/**
+ * set the status text
+ */
+void NS_Window::set_status(const char *text)
+{
+ m_status->value(text);
+}
+
+
+/**
+ * set the window title text
+ */
+void NS_Window::set_title(const char *text)
+{
+ label(text);
+}
+
+
+/**
+ * set the current position of the scroll bars
+ */
+nserror NS_Window::set_scroll(const struct rect *rect)
+{
+ m_vscrollbar->value(rect->y0);
+ m_hscrollbar->value(rect->x0);
+
+ m_nswidget->vscroll_callback(m_vscrollbar);
+ m_nswidget->hscroll_callback(m_hscrollbar);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Set the extent of the underlying canvas
+ */
+nserror NS_Window::set_extent(int ew, int eh)
+{
+ m_hscrollbar->value(0, w(), 0, ew);
+ m_vscrollbar->value(0, h(), 0, eh);
+
+ return NSERROR_OK;
+}
+
+
+/* static methods */
+
+/**
+ * static window close fltk callback which calls the instance
+ */
+void NS_Window::static_close_callback(Fl_Widget *w, void *f)
+{
+ ((NS_Window *)f)->close_callback(w);
+}
+
+/**
+ * static vertical scrollbar fltk callback which calls the instance
+ */
+void NS_Window::static_vscroll_callback(Fl_Widget *w, void *f)
+{
+ ((NS_Widget *)f)->vscroll_callback((Fl_Scrollbar *)w);
+}
+
+/**
+ * static horizontal scrollbar fltk callback which calls the instance
+ */
+void NS_Window::static_hscroll_callback(Fl_Widget *w, void *f)
+{
+ ((NS_Widget *)f)->hscroll_callback((Fl_Scrollbar *)w);
+}
+
+
+/**
+ * Set the status bar message of a browser window.
+ *
+ * \param g gui_window to update
+ * \param text new status text
+ */
+void NS_Window::static_set_status(struct gui_window *gw, const char *text)
+{
+ ((NS_Window *)gw->window)->set_status(text);
+}
+
+
+/**
+ * Set the title of a window.
+ *
+ * \param gw The gui window to set title of.
+ * \param title new window title
+ */
+void NS_Window::static_set_title(struct gui_window *gw, const char *title)
+{
+ ((NS_Window *)gw->window)->set_title(title);
+}
+
/**
* Get the scroll position of a browser window.
@@ -246,17 +489,17 @@ nsfltk_window_invalidate(struct gui_window *gw, const
struct rect *rect)
* \param sy receives y ordinate of point at top-left of window
* \return true iff successful
*/
-static bool nsfltk_window_get_scroll(struct gui_window *gw, int *sx, int *sy)
+bool NS_Window::static_get_scroll(struct gui_window *gw, int *sx, int *sy)
{
- return false;
+ return gw->window->m_nswidget->get_scroll(sx, sy);
}
/**
* Set the scroll position of a browser window.
*
- * scrolls the viewport to ensure the specified rectangle of
- * the content is shown.
+ * scrolls the viewport to ensure the specified rectangle of the
+ * content is shown.
* If the rectangle is of zero size i.e. x0 == x1 and y0 == y1
* the contents will be scrolled so the specified point in the
* content is at the top of the viewport.
@@ -268,10 +511,80 @@ static bool nsfltk_window_get_scroll(struct gui_window
*gw, int *sx, int *sy)
* \param rect The rectangle to ensure is shown.
* \return NSERROR_OK on success or appropriate error code.
*/
-static nserror
-nsfltk_window_set_scroll(struct gui_window *gw, const struct rect *rect)
+nserror
+NS_Window::static_set_scroll(struct gui_window *gw, const struct rect *rect)
{
- return NSERROR_OK;
+ return gw->window->set_scroll(rect);
+}
+
+
+/**
+ * Set the navigation url.
+ *
+ * \param gw window to update.
+ * \param url The url to use as icon.
+ */
+nserror NS_Window::static_set_url(struct gui_window *gw, struct nsurl *url)
+{
+ return gw->window->m_nsurlbar->set_url(url);
+}
+
+
+/**
+ * Miscellaneous event occurred for a window
+ *
+ * This is used to inform the frontend of window events which
+ * require no additional parameters.
+ *
+ * \param gw The gui window the event occurred for
+ * \param event Which event has occurred.
+ * \return NSERROR_OK if the event was processed else error code.
+ */
+nserror
+NS_Window::static_event(struct gui_window *gw, enum gui_window_event event)
+{
+ nserror res;
+
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ {
+ int w, h;
+
+ res = browser_window_get_extents(gw->window->m_bw, true, &w,
&h);
+ if (res == NSERROR_OK) {
+ res = (gw->window)->set_extent(w, h);
+ }
+ break;
+ }
+ default:
+ res = NSERROR_OK;
+ break;
+ }
+ return res;
+}
+
+
+/**
+ * Invalidate an area of a window.
+ *
+ * The specified area of the window should now be considered
+ * out of date. If the area is NULL the entire window must be
+ * invalidated. It is expected that the windowing system will
+ * then subsequently cause redraw/expose operations as
+ * necessary.
+ *
+ * \note the frontend should not attempt to actually start the
+ * redraw operations as a result of this callback because the
+ * core redraw functions may already be threaded.
+ *
+ * \param gw The gui window to invalidate.
+ * \param rect area to redraw or NULL for the entire window area
+ * \return NSERROR_OK on success or appropriate error code
+ */
+nserror
+NS_Window::static_invalidate(struct gui_window *gw, const struct rect *rect)
+{
+ return gw->window->m_nswidget->invalidate(rect);
}
@@ -289,47 +602,80 @@ nsfltk_window_set_scroll(struct gui_window *gw, const
struct rect *rect)
* \return NSERROR_OK on success and width and height updated
* else error code.
*/
-static nserror
-nsfltk_window_get_dimensions(struct gui_window *gw, int *width, int *height)
+nserror
+NS_Window::static_get_dimensions(struct gui_window *gw, int *width, int
*height)
{
- NS_Widget *nswidget;
- nswidget = gw->window->get_nswidget();
-
- *width = nswidget->w();
- *height = nswidget->h();
-
- return NSERROR_OK;
+ return gw->window->m_nswidget->get_dimensions(width, height);
}
/**
- * Miscellaneous event occurred for a window
+ * Create and open a gui window for a browsing context.
*
- * This is used to inform the frontend of window events which
- * require no additional parameters.
+ * The implementing front end must create a context suitable
+ * for it to display a window referred to as the "gui window".
*
- * \param gw The gui window the event occurred for
- * \param event Which event has occurred.
- * \return NSERROR_OK if the event was processed else error code.
+ * The frontend will be expected to request the core redraw
+ * areas of the gui window which have become invalidated
+ * either from toolkit expose events or as a result of a
+ * invalidate() call.
+ *
+ * Most core operations used by the frontend concerning browser
+ * windows require passing the browser window context therefor
+ * the gui window must include a reference to the browser
+ * window passed here.
+ *
+ * If GW_CREATE_CLONE flag is set existing is non-NULL.
+ *
+ * \param bw The core browsing context associated with the gui window
+ * \param existing An existing gui_window, may be NULL.
+ * \param flags flags to control the gui window creation.
+ * \return gui window, or NULL on error.
*/
-static nserror
-nsfltk_window_event(struct gui_window *gw, enum gui_window_event event)
+struct gui_window *
+NS_Window::static_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
{
- return NSERROR_OK;
+ struct gui_window *gw;
+ gw = (struct gui_window *)calloc(1, sizeof(struct gui_window));
+
+ if (gw != NULL) {
+ gw->window = new NS_Window(800,600, bw);
+
+ gw->window->show();
+ }
+
+ return gw;
}
+/**
+ * Destroy previously created gui window
+ *
+ * \param gw The gui window to destroy.
+ */
+void NS_Window::static_destroy(struct gui_window *gw)
+{
+ Fl::delete_widget(gw->window);
+ free(gw);
+}
+
+
+/**
+ * window operations table for fltk frontend
+ */
static struct gui_window_table window_table = {
- .create = nsfltk_window_create,
- .destroy = nsfltk_window_destroy,
- .invalidate = nsfltk_window_invalidate,
- .get_scroll = nsfltk_window_get_scroll,
- .set_scroll = nsfltk_window_set_scroll,
- .get_dimensions = nsfltk_window_get_dimensions,
- .event = nsfltk_window_event,
- .set_title = NULL,
- .set_url = NULL,
+ .create = NS_Window::static_create,
+ .destroy = NS_Window::static_destroy,
+ .invalidate = NS_Window::static_invalidate,
+ .get_scroll = NS_Window::static_get_scroll,
+ .set_scroll = NS_Window::static_set_scroll,
+ .get_dimensions = NS_Window::static_get_dimensions,
+ .event = NS_Window::static_event,
+ .set_title = NS_Window::static_set_title,
+ .set_url = NS_Window::static_set_url,
.set_icon = NULL,
- .set_status = NULL,
+ .set_status = NS_Window::static_set_status,
.set_pointer = NULL,
.place_caret = NULL,
.drag_start = NULL,
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc
commit 28ecbf82ed3024f51be4c87928fd91bacfc15cbc
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
Initial minimal FLTK toolkit implementation
diff --git a/frontends/Makefile.hts b/frontends/Makefile.hts
index b5af240..a78e34c 100644
--- a/frontends/Makefile.hts
+++ b/frontends/Makefile.hts
@@ -114,7 +114,7 @@ else
endif
# valid values for the TARGET
-VLDTARGET := amiga atari beos framebuffer gtk monkey riscos windows
+VLDTARGET := amiga atari beos fltk framebuffer gtk monkey riscos windows
# Check for valid TARGET
ifeq ($(filter $(VLDTARGET),$(TARGET)),)
diff --git a/frontends/fltk/Makefile b/frontends/fltk/Makefile
new file mode 100644
index 0000000..1cfb278
--- /dev/null
+++ b/frontends/fltk/Makefile
@@ -0,0 +1,35 @@
+#
+# Makefile for NetSurf ftlk target
+#
+# This file is part of NetSurf
+#
+# ----------------------------------------------------------------------------
+# FLTK flag setup (using pkg-config)
+# ----------------------------------------------------------------------------
+
+CXXFLAGS += -DFLTK_RESPATH=\"$(NETSURF_FLTK_RES_PATH)\"
+
+# fltk does not ship a pkg-config file, instead it has its own program
+
+FLTKCONFIG = fltk-config
+CXXFLAGS += $(shell $(FLTKCONFIG) --cxxflags)
+LDFLAGS += -lstdc++ $(shell $(FLTKCONFIG) --ldstaticflags)
+
+# ---------------------------------------------------------------------------
+# Target setup
+# ---------------------------------------------------------------------------
+
+# The binary target.
+EXETARGET := nsfltk
+
+# ----------------------------------------------------------------------------
+# Source file setup
+# ----------------------------------------------------------------------------
+
+# S_FRONTEND are sources purely for the FLTK frontend
+S_FRONTEND := main.cpp misc.cpp window.cpp fetch.cpp bitmap.cpp layout.cpp
plotters.cpp resources.cpp
+
+# This is the final source build list
+# Note this is deliberately *not* expanded here as common and image
+# are not yet available
+SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_RESOURCE) $(S_FRONTEND)
diff --git a/frontends/fltk/Makefile.defaults b/frontends/fltk/Makefile.defaults
new file mode 100644
index 0000000..ad70fb0
--- /dev/null
+++ b/frontends/fltk/Makefile.defaults
@@ -0,0 +1,28 @@
+# ----------------------------------------------------------------------------
+# FLTK-specific options
+# ----------------------------------------------------------------------------
+
+# Where to search for NetSurf's resources after looking in ~/.netsurf and
+# $NETSURFRES. It must have a trailing /
+NETSURF_FLTK_RES_PATH := $(PREFIX)/share/netsurf/:./frontends/fltk/res/
+
+# Where to install the netsurf binary
+NETSURF_FLTK_BIN := $(PREFIX)/bin/
+
+# Enable NetSurf's use of librsvg in conjunction with Cairo to display SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_RSVG := NO
+
+# Enable NetSurf's use of libsvgtiny for displaying SVGs
+# Valid options: YES, NO, AUTO
+NETSURF_USE_NSSVG := NO
+
+# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
+# Valid options: YES, NO, AUTO
+NETSURF_USE_ROSPRITE := NO
+
+# Enable building the source object cache filesystem based backing store.
+NETSURF_FS_BACKING_STORE := NO
+
+# Optimisation levels
+CFLAGS += -O2
diff --git a/frontends/fltk/Makefile.tools b/frontends/fltk/Makefile.tools
new file mode 100644
index 0000000..460a957
--- /dev/null
+++ b/frontends/fltk/Makefile.tools
@@ -0,0 +1,8 @@
+# -*- mode: makefile-gmake -*-
+##
+## tool setup for the fltk target
+##
+
+# use native package config
+PKG_CONFIG := pkg-config
+
diff --git a/frontends/fltk/bitmap.cpp b/frontends/fltk/bitmap.cpp
new file mode 100644
index 0000000..bc41822
--- /dev/null
+++ b/frontends/fltk/bitmap.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf bitmap for fltk.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/bitmap.h"
+
+}
+
+#include "fltk/bitmap.h"
+
+/**
+ * Create a new bitmap.
+ *
+ * \param width width of image in pixels
+ * \param height width of image in pixels
+ * \param state The state to create the bitmap in.
+ * \return A bitmap structure or NULL on error.
+ */
+static void *nsfltk_bitmap_create(int width, int height, unsigned int state)
+{
+ return NULL;
+}
+
+/**
+ * Destroy a bitmap.
+ *
+ * \param bitmap The bitmap to destroy.
+ */
+static void nsfltk_bitmap_destroy(void *bitmap)
+{
+}
+
+/**
+ * Set the opacity of a bitmap.
+ *
+ * \param bitmap The bitmap to set opacity on.
+ * \param opaque The bitmap opacity to set.
+ */
+static void nsfltk_bitmap_set_opaque(void *bitmap, bool opaque)
+{
+}
+
+/**
+ * Get the opacity of a bitmap.
+ *
+ * \param bitmap The bitmap to examine.
+ * \return The bitmap opacity.
+ */
+static bool nsfltk_bitmap_get_opaque(void *bitmap)
+{
+ return false;
+}
+
+/**
+ * Test if a bitmap is opaque.
+ *
+ * \param bitmap The bitmap to examine.
+ * \return The bitmap opacity.
+ */
+static bool nsfltk_bitmap_test_opaque(void *bitmap)
+{
+ return false;
+}
+
+/**
+ * Get the image buffer from a bitmap
+ *
+ * \param bitmap The bitmap to get the buffer from.
+ * \return The image buffer or NULL if there is none.
+ */
+static unsigned char *nsfltk_bitmap_get_buffer(void *bitmap)
+{
+ return NULL;
+}
+
+/**
+ * Get the number of bytes per row of the image
+ *
+ * \param bitmap The bitmap
+ * \return The number of bytes for a row of the bitmap.
+ */
+static size_t nsfltk_bitmap_get_rowstride(void *bitmap)
+{
+ return 0;
+}
+
+/**
+ * Get the bitmap width
+ *
+ * \param bitmap The bitmap
+ * \return The bitmap width in pixels.
+ */
+static int nsfltk_bitmap_get_width(void *bitmap)
+{
+ return 0;
+}
+
+/**
+ * Get the bitmap height
+ *
+ * \param bitmap The bitmap
+ * \return The bitmap height in pixels.
+ */
+static int nsfltk_bitmap_get_height(void *bitmap)
+{
+ return 0;
+}
+
+/**
+ * Get the *bytes* per pixel.
+ *
+ * \param bitmap The bitmap
+ */
+static size_t nsfltk_bitmap_get_bpp(void *bitmap)
+{
+ return 4;
+}
+
+/**
+ * Save a bitmap to disc.
+ *
+ * \param bitmap The bitmap to save
+ * \param path The path to save the bitmap to.
+ * \param flags Flags affecting the save.
+ */
+static bool nsfltk_bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ return false;
+}
+
+/**
+ * Marks a bitmap as modified.
+ *
+ * \param bitmap The bitmap set as modified.
+ */
+static void nsfltk_bitmap_modified(void *bitmap)
+{
+}
+
+/**
+ * Render content into a bitmap.
+ *
+ * \param bitmap The bitmap to render into.
+ * \param content The content to render.
+ */
+static nserror
+nsfltk_bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
+{
+ return NSERROR_OK;
+}
+
+
+static struct gui_bitmap_table bitmap_table = {
+ .create = nsfltk_bitmap_create,
+ .destroy = nsfltk_bitmap_destroy,
+ .set_opaque = nsfltk_bitmap_set_opaque,
+ .get_opaque = nsfltk_bitmap_get_opaque,
+ .test_opaque = nsfltk_bitmap_test_opaque,
+ .get_buffer = nsfltk_bitmap_get_buffer,
+ .get_rowstride = nsfltk_bitmap_get_rowstride,
+ .get_width = nsfltk_bitmap_get_width,
+ .get_height = nsfltk_bitmap_get_height,
+ .get_bpp = nsfltk_bitmap_get_bpp,
+ .save = nsfltk_bitmap_save,
+ .modified = nsfltk_bitmap_modified,
+ .render = nsfltk_bitmap_render,
+};
+
+struct gui_bitmap_table *nsfltk_bitmap_table = &bitmap_table;
diff --git a/frontends/fltk/bitmap.h b/frontends/fltk/bitmap.h
new file mode 100644
index 0000000..e0f01a6
--- /dev/null
+++ b/frontends/fltk/bitmap.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FLTK_BITMAP_H
+#define NETSURF_FLTK_BITMAP_H 1
+
+/**
+ * fltk bitmap operations table
+ */
+extern struct gui_bitmap_table *nsfltk_bitmap_table;
+
+#endif
diff --git a/frontends/fltk/fetch.cpp b/frontends/fltk/fetch.cpp
new file mode 100644
index 0000000..39c15a6
--- /dev/null
+++ b/frontends/fltk/fetch.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf fetch for fltk.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/filepath.h"
+#include "utils/file.h"
+#include "netsurf/fetch.h"
+
+}
+
+#include "fltk/fetch.h"
+#include "fltk/resources.h"
+
+/**
+ * Determine the MIME type of a local file.
+ *
+ * @note used in file fetcher
+ *
+ * \param unix_path Unix style path to file on disk
+ * \return Pointer to MIME type string (should not be freed) -
+ * invalidated on next call to fetch_filetype.
+ */
+static const char *nsfltk_fetch_filetype(const char *unix_path)
+{
+ int l;
+ char * res = (char*)"text/html";
+ l = strlen(unix_path);
+ NSLOG(netsurf, INFO, "unix path: %s", unix_path);
+
+
+ if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0)
+ res = (char*)"text/css";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
+ res = (char*)"text/css";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
+ res = (char*)"image/jpeg";
+ else if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)
+ res = (char*)"image/jpeg";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0)
+ res = (char*)"image/gif";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0)
+ res = (char*)"image/png";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0)
+ res = (char*)"image/jng";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0)
+ res = (char*)"image/svg";
+ else if (2 < l && strcasecmp(unix_path + l - 3, "txt") == 0)
+ res = (char*)"text/plain";
+
+ NSLOG(netsurf, INFO, "mime type: %s", res);
+ return res;
+}
+
+/**
+ * Translate resource path to full url.
+ *
+ * @note Only used in resource protocol fetcher
+ *
+ * Transforms a resource protocol path into a full URL. The returned URL
+ * is used as the target for a redirect. The caller takes ownership of
+ * the returned nsurl including unrefing it when finished with it.
+ *
+ * \param path The path of the resource to locate.
+ * \return A netsurf url object containing the full URL of the resource path
+ * or NULL if a suitable resource URL can not be generated.
+ */
+static nsurl *nsfltk_get_resource_url(const char *path)
+{
+ char buf[PATH_MAX];
+ nsurl *url = NULL;
+
+ netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url);
+
+ return url;
+}
+
+static struct gui_fetch_table fetch_table = {
+ .filetype = nsfltk_fetch_filetype,
+
+ .get_resource_url = nsfltk_get_resource_url,
+ .get_resource_data = NULL,
+ .release_resource_data = NULL,
+ .mimetype = NULL,
+};
+
+struct gui_fetch_table *nsfltk_fetch_table = &fetch_table;
diff --git a/frontends/fltk/fetch.h b/frontends/fltk/fetch.h
new file mode 100644
index 0000000..6f9913e
--- /dev/null
+++ b/frontends/fltk/fetch.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FLTK_FETCH_H
+#define NETSURF_FLTK_FETCH_H 1
+
+/**
+ * fltk fetch operations table
+ */
+extern struct gui_fetch_table *nsfltk_fetch_table;
+
+#endif
diff --git a/frontends/fltk/layout.cpp b/frontends/fltk/layout.cpp
new file mode 100644
index 0000000..4504430
--- /dev/null
+++ b/frontends/fltk/layout.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf layout operations for fltk.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/utf8.h"
+#include "netsurf/layout.h"
+#include "netsurf/plot_style.h"
+
+}
+
+#include "fltk/layout.h"
+
+/**
+ * Measure the width of a string.
+ *
+ * \param[in] fstyle plot style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[out] width updated to width of string[0..length)
+ * \return NSERROR_OK and width updated or appropriate error
+ * code on faliure
+ */
+static nserror
+nsfltk_layout_width(const struct plot_font_style *fstyle,
+ const char *string,
+ size_t length,
+ int *width)
+{
+ *width = (fstyle->size * utf8_bounded_length(string, length)) /
PLOT_STYLE_SCALE;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param[in] fstyle style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[in] x coordinate to search for
+ * \param[out] char_offset updated to offset in string of actual_x, [0..length]
+ * \param[out] actual_x updated to x coordinate of character closest to x
+ * \return NSERROR_OK and char_offset and actual_x updated or appropriate
error code on faliure
+ */
+static nserror
+nsfltk_layout_position(const struct plot_font_style *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ *char_offset = x / (fstyle->size / PLOT_STYLE_SCALE);
+ if (*char_offset > length)
+ *char_offset = length;
+ *actual_x = *char_offset * (fstyle->size / PLOT_STYLE_SCALE);
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param[in] fstyle style for this text
+ * \param[in] string UTF-8 string to measure
+ * \param[in] length length of string, in bytes
+ * \param[in] x width available
+ * \param[out] char_offset updated to offset in string of actual_x, [1..length]
+ * \param[out] actual_x updated to x coordinate of character closest to x
+ * \return NSERROR_OK or appropriate error code on faliure
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * \note char_offset of 0 must never be returned.
+ *
+ * Returns:
+ * char_offset giving split point closest to x, where actual_x <= x
+ * else
+ * char_offset giving split point closest to x, where actual_x > x
+ *
+ * Returning char_offset == length means no split possible
+ */
+static nserror
+nsfltk_layout_split(const struct plot_font_style *fstyle,
+ const char *string,
+ size_t length,
+ int x,
+ size_t *char_offset,
+ int *actual_x)
+{
+ int c_off = *char_offset = x / (fstyle->size / PLOT_STYLE_SCALE);
+ if (*char_offset > length) {
+ *char_offset = length;
+ } else {
+ while (*char_offset > 0) {
+ if (string[*char_offset] == ' ')
+ break;
+ (*char_offset)--;
+ }
+ if (*char_offset == 0) {
+ *char_offset = c_off;
+ while (*char_offset < length && string[*char_offset] !=
' ') {
+ (*char_offset)++;
+ }
+ }
+ }
+ *actual_x = *char_offset * (fstyle->size / PLOT_STYLE_SCALE);
+ return NSERROR_OK;
+}
+
+static struct gui_layout_table layout_table = {
+ .width = nsfltk_layout_width,
+ .position = nsfltk_layout_position,
+ .split = nsfltk_layout_split,
+};
+
+struct gui_layout_table *nsfltk_layout_table = &layout_table;
diff --git a/frontends/fltk/layout.h b/frontends/fltk/layout.h
new file mode 100644
index 0000000..5e19cc0
--- /dev/null
+++ b/frontends/fltk/layout.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FLTK_LAYOUT_H
+#define NETSURF_FLTK_LAYOUT_H 1
+
+/**
+ * fltk layout operations table
+ */
+extern struct gui_layout_table *nsfltk_layout_table;
+
+#endif
diff --git a/frontends/fltk/main.cpp b/frontends/fltk/main.cpp
new file mode 100644
index 0000000..ab0e1bc
--- /dev/null
+++ b/frontends/fltk/main.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <FL/Fl.H>
+
+extern "C" {
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+
+#include "netsurf/netsurf.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+
+}
+
+#include "fltk/misc.h"
+#include "fltk/window.h"
+#include "fltk/fetch.h"
+#include "fltk/bitmap.h"
+#include "fltk/layout.h"
+#include "fltk/resources.h"
+
+bool nsfltk_done = false;
+
+/**
+ * Set option defaults for fltk frontend
+ *
+ * @param defaults The option table to update.
+ * @return error status.
+ */
+static nserror set_option_defaults(struct nsoption_s *defaults)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Ensures output logging stream is correctly configured
+ */
+static bool nslog_stream_configure(FILE *fptr)
+{
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
+
+ return true;
+}
+
+
+/**
+ * fltk frontend specific initialisation
+ */
+static nserror nsfltk_init(int *pargc, char** argv)
+{
+ nserror res;
+
+ /* Prep the resource search paths */
+ res = nsfltk_init_resource_path("${HOME}/.netsurf/:${NETSURFRES}:"
FLTK_RESPATH);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "Resources failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return res;
+ }
+
+ /* Initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, pargc, argv);
+
+ /* override loaded options with those from commandline */
+ nsoption_commandline(pargc, argv, nsoptions);
+
+ /* Initialise user options */
+ res = nsoption_init(set_option_defaults, &nsoptions,
&nsoptions_default);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "Options failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return res;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Start fltk browser.
+ *
+ * performs fltk specific startup including opening initial window if necessary
+ *
+ * \param argc The number of arguments on the command line
+ * \param argv A string vector of command line arguments.
+ */
+static nserror nsfltk_start(int argc, char** argv)
+{
+ char *addr = NULL;
+ nsurl *url;
+ nserror res;
+
+ /* If there is a url specified on the command line use it */
+ if (argc > 1) {
+ struct stat fs;
+ if (stat(argv[1], &fs) == 0) {
+ size_t addrlen;
+ char *rp = realpath(argv[1], NULL);
+ assert(rp != NULL);
+
+ /* calculate file url length including terminator */
+ addrlen = SLEN("file://") + strlen(rp) + 1;
+ addr = (char *)malloc(addrlen);
+ assert(addr != NULL);
+ snprintf(addr, addrlen, "file://%s", rp);
+ free(rp);
+ } else {
+ addr = strdup(argv[1]);
+ }
+ }
+ if (addr != NULL) {
+ /* managed to set up based on local launch */
+ } else if (nsoption_charp(homepage_url) != NULL) {
+ addr = strdup(nsoption_charp(homepage_url));
+ } else {
+ addr = strdup(NETSURF_HOMEPAGE);
+ }
+
+ /* create an initial browser window */
+ res = nsurl_create(addr, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+
+ free(addr);
+
+ return res;
+}
+
+/**
+ * Run the fltk event loop.
+ *
+ */
+static void nsfltk_run(void)
+{
+ int schedtm;
+ do {
+ /* run scheduled callbacks and get the next event delta in ms */
+ schedtm = nsfltk_schedule_run();
+ Fl::wait(((double)schedtm/1000));
+ } while(nsfltk_done != true);
+}
+
+static nserror nsfltk_finalise(void)
+{
+ /* common finalisation */
+ netsurf_exit();
+
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
+
+ /* finalise logging */
+ nslog_finalise();
+
+ return NSERROR_OK;
+}
+
+/**
+ * Main entry point from OS.
+ */
+int main(int argc, char** argv)
+{
+ nserror res;
+ struct netsurf_table nsfltk_table = {
+ .misc = nsfltk_misc_table,
+ .window = nsfltk_window_table,
+ .download = NULL, /* no download functionality */
+ .clipboard = NULL, /* no clipboard functionality */
+ .fetch = nsfltk_fetch_table,
+ .file = NULL, /* use the posix default file operations */
+ .utf8 = NULL, /* use default utf-8 processing */
+ .search = NULL, /* use the default text search */
+ .search_web = NULL, /* use default web search */
+ .llcache = NULL, /* use default low level cache storage */
+ .bitmap = nsfltk_bitmap_table,
+ .layout = nsfltk_layout_table,
+ };
+
+ /* register operation tables */
+ res = netsurf_register(&nsfltk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
+ return 1;
+ }
+
+ /* fltk specific initialisation */
+ res = nsfltk_init(&argc, argv);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf fltk initialisation failed (%s)\n",
+ messages_get_errorcode(res));
+ return 2;
+ }
+
+ /* netsurf initialisation */
+ res = netsurf_init(NULL);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 3;
+ }
+
+ /* fltk specific startup */
+ res = nsfltk_start(argc, argv);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf fltk startup failed (%s)\n",
+ messages_get_errorcode(res));
+ nsfltk_finalise();
+ return 4;
+ }
+
+ /* startup suceeded so main run loop */
+ nsfltk_run();
+
+ /* finalise everything */
+ nsfltk_finalise();
+
+ return 0;
+
+}
diff --git a/frontends/fltk/misc.cpp b/frontends/fltk/misc.cpp
new file mode 100644
index 0000000..b86affd
--- /dev/null
+++ b/frontends/fltk/misc.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf miscelaneous operations for fltk.
+ */
+
+#include <stddef.h>
+#include <time.h>
+#include <stdlib.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/sys_time.h"
+#include "utils/log.h"
+#include "netsurf/misc.h"
+
+}
+
+#include "fltk/misc.h"
+
+/* linked list of scheduled callbacks */
+static struct nscallback *schedule_list = NULL;
+
+/**
+ * scheduled callback.
+ */
+struct nscallback
+{
+ struct nscallback *next;
+ struct timeval tv;
+ void (*callback)(void *p);
+ void *p;
+};
+
+/* exported function documented in fltk/misc.h */
+int nsfltk_schedule_run(void)
+{
+ struct timeval tv;
+ struct timeval nexttime;
+ struct timeval rettime;
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ if (schedule_list == NULL)
+ return -1;
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->tv;
+
+ gettimeofday(&tv, NULL);
+
+ while (cur_nscb != NULL) {
+ if (timercmp(&tv, &cur_nscb->tv, >)) {
+ /* scheduled time */
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+
+ if (prev_nscb == NULL) {
+ schedule_list = unlnk_nscb->next;
+ } else {
+ prev_nscb->next = unlnk_nscb->next;
+ }
+
+ unlnk_nscb->callback(unlnk_nscb->p);
+
+ free(unlnk_nscb);
+
+ /* need to deal with callback modifying the list. */
+ if (schedule_list == NULL)
+ return -1; /* no more callbacks scheduled */
+
+ /* reset enumeration to the start of the list */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+ nexttime = cur_nscb->tv;
+ } else {
+ /* if the time to the event is sooner than the
+ * currently recorded soonest event record it
+ */
+ if (timercmp(&nexttime, &cur_nscb->tv, >)) {
+ nexttime = cur_nscb->tv;
+ }
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ /* make rettime relative to now */
+ timersub(&nexttime, &tv, &rettime);
+
+ NSLOG(schedule, DEBUG, "returning time to next event as %ldms",
+ (long)((rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)));
+
+ /* return next event time in milliseconds (24days max wait) */
+ return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
+}
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ * \return NSERROR_OK if callback found and removed else NSERROR_NOT_FOUND
+ *
+ * All scheduled callbacks matching both callback and p are removed.
+ */
+static nserror schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+ bool removed = false;
+
+ /* check there is something on the list to remove */
+ if (schedule_list == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ NSLOG(schedule, DEBUG, "removing %p, %p", callback, p);
+
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ while (cur_nscb != NULL) {
+ if ((cur_nscb->callback == callback) &&
+ (cur_nscb->p == p)) {
+ /* item to remove */
+
+ NSLOG(schedule, DEBUG, "callback entry %p removing
%p(%p)",
+ cur_nscb, cur_nscb->callback, cur_nscb->p);
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+ cur_nscb = unlnk_nscb->next;
+
+ if (prev_nscb == NULL) {
+ schedule_list = cur_nscb;
+ } else {
+ prev_nscb->next = cur_nscb;
+ }
+ free (unlnk_nscb);
+ removed = true;
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+
+ if (removed == false) {
+ return NSERROR_NOT_FOUND;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made in ms or
+ * negative value to remove any existing callback.
+ * \param callback callback function
+ * \param p user parameter passed to callback function
+ * \return NSERROR_OK on sucess or appropriate error on faliure
+ *
+ * The callback function will be called as soon as possible
+ * after the timeout has elapsed.
+ *
+ * Additional calls with the same callback and user parameter will
+ * reset the callback time to the newly specified value.
+ *
+ */
+static nserror nsfltk_schedule(int tival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+ nserror ret;
+
+ /* ensure uniqueness of the callback and context */
+ ret = schedule_remove(callback, p);
+ if (tival < 0) {
+ return ret;
+ }
+
+ NSLOG(schedule, DEBUG, "Adding %p(%p) in %d", callback, p, tival);
+
+ tv.tv_sec = tival / 1000; /* miliseconds to seconds */
+ tv.tv_usec = (tival % 1000) * 1000; /* remainder to microseconds */
+
+ nscb = (struct nscallback*)calloc(1, sizeof(struct nscallback));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+
+ return NSERROR_OK;
+}
+
+static struct gui_misc_table misc_table = {
+ .schedule = nsfltk_schedule,
+ .quit = NULL,
+ .launch_url = NULL,
+ .login = NULL,
+ .pdf_password = NULL,
+ .present_cookies = NULL,
+};
+
+struct gui_misc_table *nsfltk_misc_table = &misc_table;
diff --git a/frontends/fltk/misc.h b/frontends/fltk/misc.h
new file mode 100644
index 0000000..e088043
--- /dev/null
+++ b/frontends/fltk/misc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FLTK_MISC_H
+#define NETSURF_FLTK_MISC_H 1
+
+/**
+ * fltk miscellaneous (scheduling) operations table
+ */
+extern struct gui_misc_table *nsfltk_misc_table;
+
+/**
+ * run and pending scheduling callbacks
+ *
+ * \return number of miliseconds before next scheduled event
+ */
+int nsfltk_schedule_run(void);
+
+#endif
diff --git a/frontends/fltk/plotters.cpp b/frontends/fltk/plotters.cpp
new file mode 100644
index 0000000..65268f1
--- /dev/null
+++ b/frontends/fltk/plotters.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of plotters for fltk.
+ */
+
+#include <stddef.h>
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/types.h"
+#include "netsurf/mouse.h"
+#include "netsurf/window.h"
+#include "netsurf/plotters.h"
+
+}
+
+#include "fltk/window.h"
+#include "fltk/plotters.h"
+
+
+static inline void nsfltk_set_colour(colour c)
+{
+ fl_color(fl_rgb_color((c & 0xff),
+ ((c & 0xff00) >> 8),
+ ((c & 0xff0000) >> 16)));
+}
+
+
+/**
+ * \brief Sets a clip rectangle for subsequent plot operations.
+ *
+ * \param ctx The current redraw context.
+ * \param clip The rectangle to limit all subsequent plot
+ * operations within.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a circle
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the circle plot.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a line
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at
+ * centre of line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the line plot.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
+{
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfltk_set_colour(style->stroke_colour);
+ fl_line(line->x0, line->y0, line->x1, line->y1);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a rectangle.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the rectangle plot.
+ * \param rect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *rect)
+{
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfltk_set_colour(style->fill_colour);
+ fl_rectf(rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfltk_set_colour(style->stroke_colour);
+ fl_rect(rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plot a polygon
+ *
+ * Plots a filled polygon with straight lines between
+ * points. The lines around the edge of the ploygon are not
+ * plotted. The polygon is filled with the non-zero winding
+ * rule.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plots a path.
+ *
+ * Path plot consisting of cubic Bezier curves. Line and fill colour is
+ * controlled by the plot style.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ const float transform[6])
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Plot a bitmap
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsfltk_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ nsfltk_set_colour(fstyle->foreground);
+ fl_draw(text,length,x,y);
+ return NSERROR_OK;
+}
+
+
+/**
+ * FLTK plotter table
+ */
+const struct plotter_table nsfltk_plotters = {
+ .clip = nsfltk_plot_clip,
+ .arc = nsfltk_plot_arc,
+ .disc = nsfltk_plot_disc,
+ .line = nsfltk_plot_line,
+ .rectangle = nsfltk_plot_rectangle,
+ .polygon = nsfltk_plot_polygon,
+ .path = nsfltk_plot_path,
+ .bitmap = nsfltk_plot_bitmap,
+ .text = nsfltk_plot_text,
+ .group_start = NULL,
+ .group_end = NULL,
+ .flush = NULL,
+ .option_knockout = true
+};
diff --git a/frontends/fltk/plotters.h b/frontends/fltk/plotters.h
new file mode 100644
index 0000000..f0c8df9
--- /dev/null
+++ b/frontends/fltk/plotters.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Target independent plotting FLGTK+ interface.
+ */
+
+#ifndef NETSURF_FLTK_PLOTTERS_H
+#define NETSURF_FLTK_PLOTTERS_H 1
+
+struct plotter_table;
+
+extern const struct plotter_table nsfltk_plotters;
+
+#endif /* NETSURF_FLTK_PLOTTERS_H */
+
diff --git a/frontends/fltk/res/adblock.css b/frontends/fltk/res/adblock.css
new file mode 120000
index 0000000..0d12aaa
--- /dev/null
+++ b/frontends/fltk/res/adblock.css
@@ -0,0 +1 @@
+../../../resources/adblock.css
\ No newline at end of file
diff --git a/frontends/fltk/res/default.css b/frontends/fltk/res/default.css
new file mode 120000
index 0000000..fa3ae6c
--- /dev/null
+++ b/frontends/fltk/res/default.css
@@ -0,0 +1 @@
+../../../resources/default.css
\ No newline at end of file
diff --git a/frontends/fltk/res/en/credits.html
b/frontends/fltk/res/en/credits.html
new file mode 120000
index 0000000..f73ecd4
--- /dev/null
+++ b/frontends/fltk/res/en/credits.html
@@ -0,0 +1 @@
+../../../../resources/en/credits.html
\ No newline at end of file
diff --git a/frontends/fltk/res/en/licence.html
b/frontends/fltk/res/en/licence.html
new file mode 120000
index 0000000..0c3b430
--- /dev/null
+++ b/frontends/fltk/res/en/licence.html
@@ -0,0 +1 @@
+../../../../resources/en/licence.html
\ No newline at end of file
diff --git a/frontends/fltk/res/en/welcome.html
b/frontends/fltk/res/en/welcome.html
new file mode 120000
index 0000000..543f31d
--- /dev/null
+++ b/frontends/fltk/res/en/welcome.html
@@ -0,0 +1 @@
+../../../../resources/en/welcome.html
\ No newline at end of file
diff --git a/frontends/fltk/res/internal.css b/frontends/fltk/res/internal.css
new file mode 120000
index 0000000..5583a98
--- /dev/null
+++ b/frontends/fltk/res/internal.css
@@ -0,0 +1 @@
+../../../resources/internal.css
\ No newline at end of file
diff --git a/frontends/fltk/res/netsurf.png b/frontends/fltk/res/netsurf.png
new file mode 120000
index 0000000..d0ab72a
--- /dev/null
+++ b/frontends/fltk/res/netsurf.png
@@ -0,0 +1 @@
+../../../resources/netsurf.png
\ No newline at end of file
diff --git a/frontends/fltk/res/quirks.css b/frontends/fltk/res/quirks.css
new file mode 120000
index 0000000..1e752cb
--- /dev/null
+++ b/frontends/fltk/res/quirks.css
@@ -0,0 +1 @@
+../../../resources/quirks.css
\ No newline at end of file
diff --git a/frontends/fltk/resources.cpp b/frontends/fltk/resources.cpp
new file mode 100644
index 0000000..78925eb
--- /dev/null
+++ b/frontends/fltk/resources.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "utils/filepath.h"
+
+}
+
+#include "fltk/resources.h"
+
+/** resource search path vector */
+char **respaths;
+
+/** maximum number of languages in language vector */
+#define LANGV_SIZE 32
+/** maximum length of all strings in language vector */
+#define LANGS_SIZE 4096
+
+/**
+ * obtain language from environment
+ *
+ * start with GNU extension LANGUAGE environment variable and then try
+ * POSIX variables LC_ALL, LC_MESSAGES and LANG
+ *
+ */
+static const char *get_language(void)
+{
+ const char *lang;
+
+ lang = getenv("LANGUAGE");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ lang = getenv("LC_ALL");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ lang = getenv("LC_MESSAGES");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ lang = getenv("LANG");
+ if ((lang != NULL) && (lang[0] != '\0')) {
+ return lang;
+ }
+
+ return NULL;
+}
+
+
+/** provide a string vector of languages in preference order
+ *
+ * environment variables are processed to aquire a colon separated
+ * list of languages which are converted into a string vector. The
+ * vector will always have the C language as its last entry.
+ *
+ * This implementation creates an internal static representation of
+ * the vector when first called and returns that for all subsequent
+ * calls. i.e. changing the environment does not change the returned
+ * vector on repeated calls.
+ *
+ * If the environment variables have more than LANGV_SIZE languages or
+ * LANGS_SIZE bytes of data the results list will be curtailed.
+ */
+static const char * const *get_languagev(void)
+{
+ static const char *langv[LANGV_SIZE];
+ int langidx = 0; /* index of next entry in vector */
+ static char langs[LANGS_SIZE];
+ char *curp; /* next language parameter in langs string */
+ const char *lange; /* language from environment variable */
+ int lang_len;
+ char *cln; /* colon in lange */
+
+ /* return cached vector */
+ if (langv[0] != NULL) {
+ return &langv[0];
+ }
+
+ curp = &langs[0];
+
+ lange = get_language();
+
+ if (lange != NULL) {
+ lang_len = strlen(lange) + 1;
+ if (lang_len < (LANGS_SIZE - 2)) {
+ memcpy(curp, lange, lang_len);
+ while ((curp[0] != 0) &&
+ (langidx < (LANGV_SIZE - 2))) {
+ /* avoid using strchrnul as it is not portable
*/
+ cln = strchr(curp, ':');
+ if (cln == NULL) {
+ langv[langidx++] = curp;
+ curp += lang_len;
+ break;
+ } else {
+ if ((cln - curp) > 1) {
+ /* only place non empty entries
in vector */
+ langv[langidx++] = curp;
+ }
+ *cln++ = 0; /* null terminate */
+ lang_len -= (cln - curp);
+ curp = cln;
+ }
+ }
+ }
+ }
+
+ /* ensure C language is present */
+ langv[langidx++] = curp;
+ *curp++ = 'C';
+ *curp++ = 0;
+ langv[langidx] = NULL;
+
+ return &langv[0];
+}
+
+
+/* exported interface documented in fltk/resources.h */
+nserror nsfltk_init_resource_path(const char *resource_path)
+{
+ const char * const *langv;
+ char **pathv; /* resource path string vector */
+
+ pathv = filepath_path_to_strvec(resource_path);
+
+ langv = get_languagev();
+
+ respaths = filepath_generate(pathv, langv);
+
+ filepath_free_strvec(pathv);
+
+ return NSERROR_OK;
+}
diff --git a/frontends/fltk/resources.h b/frontends/fltk/resources.h
new file mode 100644
index 0000000..849179b
--- /dev/null
+++ b/frontends/fltk/resources.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FLTK_RESOURCES_H
+#define NETSURF_FLTK_RESOURCES_H 1
+
+/**
+ * resource search path vector
+ */
+extern char **respaths;
+
+/**
+ * Create an array of valid paths to search for resources.
+ *
+ * The idea is that all the complex path computation to find resources
+ * is performed here, once, rather than every time a resource is
+ * searched for.
+ *
+ * \param resource_path A shell style colon separated path list
+
+ * \return NSERROR_OK on success and the respaths set to a string
+ * vector of valid paths where resources can be found or appropriate
+ * error code on faliure.
+ */
+nserror nsfltk_init_resource_path(const char *resource_path);
+
+#endif
diff --git a/frontends/fltk/window.cpp b/frontends/fltk/window.cpp
new file mode 100644
index 0000000..19aa265
--- /dev/null
+++ b/frontends/fltk/window.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf window (widget) for fltk.
+ */
+
+#include <stddef.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/fl_draw.H>
+
+extern "C" {
+
+#include "utils/errors.h"
+#include "netsurf/types.h"
+#include "netsurf/mouse.h"
+#include "netsurf/window.h"
+#include "netsurf/plotters.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/mouse.h"
+
+}
+
+#include "fltk/window.h"
+#include "fltk/plotters.h"
+
+extern bool nsfltk_done;
+
+class NS_Widget : public Fl_Widget
+{
+private:
+ struct browser_window *mbw;
+
+protected:
+ void draw();
+ int handle(int event);
+
+public:
+ NS_Widget(int X,int Y,int W,int H, struct browser_window *bw)
+ : Fl_Widget(X,Y,W,H), mbw(bw) {}
+};
+
+
+class NS_Window : public Fl_Double_Window
+{
+private:
+ struct browser_window *mbw;
+ NS_Widget *mnswidget;
+
+ void close_callback(Fl_Widget *w);
+ static void static_close_callback(Fl_Widget *w, void *f) { ((NS_Window
*)f)->close_callback(w); }
+
+public:
+ NS_Window(int W, int H, struct browser_window *bw)
+ : Fl_Double_Window(W,H), mbw(bw) {
+ this->callback(static_close_callback, (void *)this);
+ mnswidget = new NS_Widget(0, 0, W, H, bw);
+ this->end();
+ }
+ ~NS_Window() { nsfltk_done=true; }
+
+ NS_Widget *get_nswidget() { return mnswidget; }
+};
+
+struct gui_window {
+ struct browser_window *bw;
+ NS_Window *window;
+};
+
+/**
+ * method to handle events on the netsurf browsing widget
+ */
+int NS_Widget::handle(int event)
+{
+ int state = BROWSER_MOUSE_HOVER;
+ int button;
+
+ switch (event) {
+ case FL_PUSH:
+ button = Fl::event_button();
+ if (button == FL_LEFT_MOUSE) {
+ state |= BROWSER_MOUSE_PRESS_1;
+ }
+ browser_window_mouse_click(mbw,
+ (browser_mouse_state)state,
+ Fl::event_x() - x(),
+ Fl::event_y() - y());
+ return 1;
+
+ case FL_RELEASE:
+ button = Fl::event_button();
+ if (button == FL_LEFT_MOUSE) {
+ state |= BROWSER_MOUSE_CLICK_1;
+
+ }
+ browser_window_mouse_click(mbw,
+ (browser_mouse_state)state,
+ Fl::event_x() - x(),
+ Fl::event_y() - y());
+
+ return 1;
+ default:
+ return Fl_Widget::handle(event);
+ }
+}
+
+
+/**
+ * method to redraw the netsurf browsing widget
+ */
+void NS_Widget::draw()
+{
+ struct rect clip;
+ fl_clip_box(x(), y(), w(), h(), clip.x0, clip.y0, clip.x1, clip.y1);
+ /* clip box generates width/height so convert to absolute */
+ clip.x1 += clip.x0;
+ clip.y1 += clip.y0;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &nsfltk_plotters,
+ .priv = NULL,
+ };
+
+ browser_window_redraw(mbw, x(), y(), &clip, &ctx);
+
+}
+
+/**
+ * callback when fltk window is closed
+ */
+void NS_Window::close_callback(Fl_Widget *w)
+{
+ browser_window_destroy(mbw);
+}
+
+/**
+ * Create and open a gui window for a browsing context.
+ *
+ * The implementing front end must create a context suitable
+ * for it to display a window referred to as the "gui window".
+ *
+ * The frontend will be expected to request the core redraw
+ * areas of the gui window which have become invalidated
+ * either from toolkit expose events or as a result of a
+ * invalidate() call.
+ *
+ * Most core operations used by the frontend concerning browser
+ * windows require passing the browser window context therefor
+ * the gui window must include a reference to the browser
+ * window passed here.
+ *
+ * If GW_CREATE_CLONE flag is set existing is non-NULL.
+ *
+ * \param bw The core browsing context associated with the gui window
+ * \param existing An existing gui_window, may be NULL.
+ * \param flags flags to control the gui window creation.
+ * \return gui window, or NULL on error.
+ */
+static struct gui_window *
+nsfltk_window_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
+{
+ struct gui_window *gw;
+ gw = (struct gui_window *)calloc(1, sizeof(struct gui_window));
+
+ gw->window = new NS_Window(800,600, bw);
+
+ gw->window->show();
+
+ return gw;
+}
+
+/**
+ * Destroy previously created gui window
+ *
+ * \param gw The gui window to destroy.
+ */
+static void nsfltk_window_destroy(struct gui_window *gw)
+{
+ Fl::delete_widget(gw->window);
+ free(gw);
+}
+
+
+/**
+ * Invalidate an area of a window.
+ *
+ * The specified area of the window should now be considered
+ * out of date. If the area is NULL the entire window must be
+ * invalidated. It is expected that the windowing system will
+ * then subsequently cause redraw/expose operations as
+ * necessary.
+ *
+ * \note the frontend should not attempt to actually start the
+ * redraw operations as a result of this callback because the
+ * core redraw functions may already be threaded.
+ *
+ * \param gw The gui window to invalidate.
+ * \param rect area to redraw or NULL for the entire window area
+ * \return NSERROR_OK on success or appropriate error code
+ */
+static nserror
+nsfltk_window_invalidate(struct gui_window *gw, const struct rect *rect)
+{
+ NS_Widget *nswidget;
+ nswidget = gw->window->get_nswidget();
+
+ if (rect == NULL) {
+ nswidget->damage(FL_DAMAGE_ALL);
+ } else {
+ nswidget->damage(FL_DAMAGE_ALL,
+ rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * Get the scroll position of a browser window.
+ *
+ * \param gw The gui window to obtain the scroll position from.
+ * \param sx receives x ordinate of point at top-left of window
+ * \param sy receives y ordinate of point at top-left of window
+ * \return true iff successful
+ */
+static bool nsfltk_window_get_scroll(struct gui_window *gw, int *sx, int *sy)
+{
+ return false;
+}
+
+
+/**
+ * Set the scroll position of a browser window.
+ *
+ * scrolls the viewport to ensure the specified rectangle of
+ * the content is shown.
+ * If the rectangle is of zero size i.e. x0 == x1 and y0 == y1
+ * the contents will be scrolled so the specified point in the
+ * content is at the top of the viewport.
+ * If the size of the rectangle is non zero the frontend may
+ * add padding or centre the defined area or it may simply
+ * align as in the zero size rectangle
+ *
+ * \param gw The gui window to scroll.
+ * \param rect The rectangle to ensure is shown.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+nsfltk_window_set_scroll(struct gui_window *gw, const struct rect *rect)
+{
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find the current dimensions of a browser window's content area.
+ *
+ * This is used to determine the actual available drawing size
+ * in pixels. This allows contents that can be dynamically
+ * reformatted, such as HTML, to better use the available
+ * space.
+ *
+ * \param gw The gui window to measure content area of.
+ * \param width receives width of window
+ * \param height receives height of window
+ * \return NSERROR_OK on success and width and height updated
+ * else error code.
+ */
+static nserror
+nsfltk_window_get_dimensions(struct gui_window *gw, int *width, int *height)
+{
+ NS_Widget *nswidget;
+ nswidget = gw->window->get_nswidget();
+
+ *width = nswidget->w();
+ *height = nswidget->h();
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Miscellaneous event occurred for a window
+ *
+ * This is used to inform the frontend of window events which
+ * require no additional parameters.
+ *
+ * \param gw The gui window the event occurred for
+ * \param event Which event has occurred.
+ * \return NSERROR_OK if the event was processed else error code.
+ */
+static nserror
+nsfltk_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ return NSERROR_OK;
+}
+
+static struct gui_window_table window_table = {
+ .create = nsfltk_window_create,
+ .destroy = nsfltk_window_destroy,
+ .invalidate = nsfltk_window_invalidate,
+ .get_scroll = nsfltk_window_get_scroll,
+ .set_scroll = nsfltk_window_set_scroll,
+ .get_dimensions = nsfltk_window_get_dimensions,
+ .event = nsfltk_window_event,
+ .set_title = NULL,
+ .set_url = NULL,
+ .set_icon = NULL,
+ .set_status = NULL,
+ .set_pointer = NULL,
+ .place_caret = NULL,
+ .drag_start = NULL,
+ .save_link = NULL,
+ .create_form_select_menu = NULL,
+ .file_gadget_open = NULL,
+ .drag_save_object = NULL,
+ .drag_save_selection = NULL,
+ .console_log = NULL,
+};
+
+struct gui_window_table *nsfltk_window_table = &window_table;
diff --git a/frontends/fltk/window.h b/frontends/fltk/window.h
new file mode 100644
index 0000000..c339418
--- /dev/null
+++ b/frontends/fltk/window.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_FLTK_WINDOW_H
+#define NETSURF_FLTK_WINDOW_H 1
+
+/**
+ * fltk window (browser widget) operations table
+ */
+extern struct gui_window_table *nsfltk_window_table;
+
+#endif
-----------------------------------------------------------------------
Summary of changes:
Makefile.macros | 2 +-
desktop/browser_history.c | 11 +-
desktop/browser_history.h | 11 -
desktop/local_history.c | 1 +
.../textplain.h => desktop/local_history_private.h | 23 +-
docs/development.md | 6 +
docs/implementing-new-frontend.md | 352 +++++++++++
frontends/fltk/main.cpp | 3 -
frontends/fltk/window.cpp | 618 +++++++++++++++-----
9 files changed, 858 insertions(+), 169 deletions(-)
copy content/handlers/text/textplain.h => desktop/local_history_private.h (57%)
create mode 100644 docs/implementing-new-frontend.md
diff --git a/Makefile.macros b/Makefile.macros
index d8468b4..9421acf 100644
--- a/Makefile.macros
+++ b/Makefile.macros
@@ -207,7 +207,7 @@ $$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created
$$(DEPROOT)/created
$$(Q)$$(RM) $$(DEPROOT)/$(3)
$$(Q)$$(RM) $$(OBJROOT)/$(2)
$$(Q)$$(CC) $$(COMMON_WARNFLAGS) $$(CWARNFLAGS) $$(IFLAGS) $$(CFLAGS)
$(CFLAGS_ENV) \
- -MMD -MT '$$(DEPROOT)/$(3) $$(OBJROOT)/$(2)' \
+ -MMD -MP -MT '$$(DEPROOT)/$(3) $$(OBJROOT)/$(2)' \
-MF $$(DEPROOT)/$(3) -o $$(OBJROOT)/$(2) -c $(1)
endef
diff --git a/desktop/browser_history.c b/desktop/browser_history.c
index 5b44670..2fbc80f 100644
--- a/desktop/browser_history.c
+++ b/desktop/browser_history.c
@@ -41,6 +41,7 @@
#include "desktop/gui_internal.h"
#include "desktop/browser_private.h"
+#include "desktop/local_history_private.h"
#include "desktop/browser_history.h"
/**
@@ -434,9 +435,7 @@ nserror browser_window_history_update(struct browser_window
*bw,
history = bw->history;
- if (!history ||
- !history->current ||
- !history->current->page.bitmap) {
+ if ((history == NULL) || (history->current == NULL)) {
return NSERROR_INVALID;
}
@@ -455,7 +454,7 @@ nserror browser_window_history_update(struct browser_window
*bw,
guit->bitmap->render(history->current->page.bitmap, content);
}
- if (bw->window != NULL &&
+ if ((bw->window != NULL) &&
guit->window->get_scroll(bw->window, &sx, &sy)) {
int content_height = content_get_height(content);
int content_width = content_get_width(content);
@@ -489,9 +488,7 @@ browser_window_history_get_scroll(struct browser_window *bw,
history = bw->history;
- if (!history ||
- !history->current ||
- !history->current->page.bitmap) {
+ if ((history== NULL) || (history->current == NULL)) {
return NSERROR_INVALID;
}
diff --git a/desktop/browser_history.h b/desktop/browser_history.h
index 06041eb..9b6f1fd 100644
--- a/desktop/browser_history.h
+++ b/desktop/browser_history.h
@@ -35,17 +35,6 @@
#include "utils/errors.h"
-#include "content/handlers/css/utils.h"
-
-#define LOCAL_HISTORY_WIDTH \
- (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(116))))
-#define LOCAL_HISTORY_HEIGHT \
- (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(100))))
-#define LOCAL_HISTORY_RIGHT_MARGIN \
- (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(50))))
-#define LOCAL_HISTORY_BOTTOM_MARGIN \
- (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(30))))
-
struct browser_window;
struct history_entry;
struct bitmap;
diff --git a/desktop/local_history.c b/desktop/local_history.c
index 412e893..5227c97 100644
--- a/desktop/local_history.c
+++ b/desktop/local_history.c
@@ -41,6 +41,7 @@
#include "desktop/system_colour.h"
#include "desktop/browser_private.h"
#include "desktop/browser_history.h"
+#include "desktop/local_history_private.h"
#include "desktop/local_history.h"
/**
diff --git a/content/handlers/text/textplain.h b/desktop/local_history_private.h
similarity index 57%
copy from content/handlers/text/textplain.h
copy to desktop/local_history_private.h
index 6cc2716..0b74562 100644
--- a/content/handlers/text/textplain.h
+++ b/desktop/local_history_private.h
@@ -1,6 +1,5 @@
/*
* Copyright 2006 James Bursa <[email protected]>
- * Copyright 2006 Adrian Lees <[email protected]>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -19,19 +18,21 @@
/**
* \file
- *
- * Interface to content handler for plain text.
+ * Interface to browser history private operations
*/
-#ifndef NETSURF_HTML_TEXTPLAIN_H
-#define NETSURF_HTML_TEXTPLAIN_H
+#ifndef NETSURF_DESKTOP_BROWSER_HISTORY_PRIVATE_H
+#define NETSURF_DESKTOP_BROWSER_HISTORY_PRIVATE_H
-/**
- * Initialise the text content handler
- *
- * \return NSERROR_OK on success else appropriate error code.
- */
-nserror textplain_init(void);
+#include "content/handlers/css/utils.h"
+#define LOCAL_HISTORY_WIDTH \
+ (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(116))))
+#define LOCAL_HISTORY_HEIGHT \
+ (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(100))))
+#define LOCAL_HISTORY_RIGHT_MARGIN \
+ (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(50))))
+#define LOCAL_HISTORY_BOTTOM_MARGIN \
+ (FIXTOINT(nscss_pixels_css_to_physical(INTTOFIX(30))))
#endif
diff --git a/docs/development.md b/docs/development.md
index 5a8d1aa..3f08b54 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -69,6 +69,12 @@ NetSurf [integration tests](docs/integration-testing.md) use
the
monkey frontend to operate the browser as a whole. These tests open
windows, navigate to websites and render contents as a user might.
+# New frontend development
+
+[Implementing a new frotend](docs/implementing-new-frontend.md) for a
+toolkit can be challenging and this guide provides an overview and
+worked example.
+
# Documented API
The NetSurf code makes use of Doxygen for code documentation.
diff --git a/docs/implementing-new-frontend.md
b/docs/implementing-new-frontend.md
new file mode 100644
index 0000000..1b4e438
--- /dev/null
+++ b/docs/implementing-new-frontend.md
@@ -0,0 +1,352 @@
+Implementing a new frontend
+===========================
+
+[TOC]
+
+# Introduction
+
+NetSurf is divided into a series of frontends which provide a user
+interface around common core functionality.
+
+Each frontend is a distinct implementation for a specific GUI toolkit.
+
+The existing frontends are covered in the [user
+interface](docs/user-interface.md) documentation.
+
+Note implementing a new frontend implies using a toolkit distinct from
+one of those already implemented and is distinct from porting NetSurf
+to a new operating system platform.
+
+It is recommend, in the strongest terms, that if the prospective
+developer is porting to both a new platform and toolkit that they
+*start* by getting the [monkey](docs/using-monkey.md) frontend
+building and passing at least the basic integration tests on their
+platform.
+
+Experience has shown that attempting to port to a platform and
+implement a toolkit at the same time generally results in failure to
+achieve either goal.
+
+NetSurf is built using GNU make and frontends are expected to
+integrate with this buildsystem.
+
+Implementation languages have historically been limited to C, C++ and
+objective C. However any language that can call C functions and
+*importantly* be called back from C code ought to be usable. For
+example there have been experiments with JAVA using JNI but no current
+frontend is implemented using it.
+
+# Implementation complexity
+
+An absolutely minimal "proof of concept" frontend implementation (like
+the FLTK frontend that will be used as an example) is around 1,000
+lines of C code. Basic functionality like the windows frontend is
+around 7,000 lines. A complete fully functional frontend such as the
+one for GTK is closer to 15,000 lines.
+
+It should be noted the majority of the minimal implementation can
+simply be copied and the names changed as appropriate from an existing
+example. The actual amount of new code that needs to be provided is
+very small.
+
+NetSurf provides a great deal of generic functionality for things like
+cookie, bookmark, history windows which require only minimal frontend
+support with the [core window API](docs/core-window-interface.md).
+
+A frontend developer is free to implement any and all of this generic
+functionality thelselves in a manner more integrated into a toolkit.
+
+# Implementation
+
+A frontend is generally named for the toolkit it is implementing (i.e
+gtk for the GTK+ toolkit). It is advisable to be as specific as
+possible e.g. the frontend for the windows operating system should
+have been named win32 allowing for an impementation using a differnt
+toolkit (e.g mfc)
+
+All the files needed for the frontend are contained in a single
+sub-directory in the NetSurf source tree e.g. `frontends/fltk`
+
+The only file outside this directory that much be changed is the
+`frontends/Makefile.hts` where a new entry must be added to the valid
+targets list.
+
+## Build system
+
+A frontend must provide three GNU Makefile fragments (these will be
+included from the core Makefile):
+
+ - `Makefile` - This is used to extend CFLAGS, CXXFLAGS and LDFLAGS variables
as required. The executable target is set with EXETARGET and the browser source
files are listed in the SOURCES variable
+ - `Makefile.defaults` - allows setting frontend specific makefile variables
and overriding of the default core build variables.
+ - `Makefile.tools` - allows setting up frontend specific build tooling (as a
minimum a tool for the package configuration in PKG_CONFIG)
+
+Source code modules can be named as the devloper desires within the
+frontend directory and should be added to the SOURCES variable as
+desired.
+
+## Program entry
+
+Generally the entry point from the OS is the `main()` function and
+several frontends have a `main.cpp` where some have used `gui.c`.
+
+The usual shape for the `main()` function is a six step process:
+ 1. The frontends operation tables are registered with NetSurf
+ 2. The toolkit specific initialisation is performed (which may involve
calling NetSurf provided utility functions for support operations like logging,
message translations etc.)
+ 3. Initialise the NetSurf core. After this point all browser functionality is
available and registered operations can be called.
+ 4. Perform toolkiit setup, usually opening the initial browsing window
(perhaps according to user preferences)
+ 5. Run the toolkits main loop while ensuring the Netsurf scheduled operations
are also run at teh apropriate time.
+ 6. Finalisation on completion.
+
+## NetSurf operations tables
+
+The frontend will generally call netsurf interfaces to get a desired
+behaviour e.g. `browser_window_create()` to create a new browsing
+context (the `browser_window_` prefix is historical and does not
+necessarily create a window e.g. on gtk it is more likely to open a
+tab in an existing window). To achive the desired operation some
+operations need to be performed by the frontend under control of
+NetSurf, these operations are listed in tables.
+
+The operation tables should be registered with the NetSurf core as one
+of the first operations of the frontend code. The functions in these
+tables (and the tables themselves) must remain valid until
+`netsurf_exit()` is called.
+
+There are (currently) twelve sets of operation tables held in separate
+structures. Only five of these are mandantory (misc, window, fetch,
+bitmap and layout).
+
+In this context mandantory means the tables must be non NULL and do
+not have a suitable default. Each of the mandantory sets contain
+function pointers to implement operations.
+
+### misc operation table
+
+The only mandantory operation in this table is schedule.
+
+When schedule is called the frontend must arrange for the passed
+callback to be called with the context parameter after a number of
+miliseconds.
+
+This callback is typicaly driven through the toolkits event loop and
+it is important such callbacks are not attempted from an operation.
+
+### window operation table
+
+The window operations (poorly named as already mentioned) are where
+the frontend is called to actually manipulate widgets in the
+toolkit. This is mediated through a `gui_window` context pointer which
+is typed as a structure.
+
+This context pointer is passed to all window operations and is
+generally assumed to contain at least a reference to the underlying
+`browser_window` which is provided in the initial create operation to
+allow subsequent use of various core functionality.
+
+The mandantory window operations are:
+ - create - create a new browsing context widget in the frontend toolkit
+ - destroy - destoy a previously created `gui_window`
+ - invalidate - mark an area of the browsing context viewport as requiring
redraw (note no redraw should be attempted from here)
+ - get_scroll - get the scroll offsets from the toolkit drawing widget
+ - set_scroll - set the scroll offsets on the toolkit drawing widget
+ - get_dimensions - get the dimensions of the toolkit drawing widget
+ - event - deal with various window events from netsurf which have no
additional parameters
+
+
+### fetch operation table
+
+The fetch operations allow the built in scheme fetchers (file, about,
resource) to obtain additional information necessary to complete their
operation.
+
+The two mandantory operations are:
+ - `filetype` - allows the file scheme to obtain a mime type from a file path
e.g. `a.file.name.png` would result in `image/png`
+ - `get_resource_url` - maps resource scheme paths to URL e.g.
`resource:default.css` to `file:///usr/share/netsurf/default.css`
+
+### bitmap operation table
+
+The bitmap table and all of its operations are mandantory only because
+the empty defaults have not been included as it is assumed a browser
+will want to display images.
+
+All operations may be provided by stubs that return the failure codes
+until full implementations are made.
+
+### layout operation table
+
+The layout table is used to layout text. All operations are given
+strings to manipulate encoded in UTF-8. There are three mandantory
+operations:
+ - `width` - Calculate the width of a string.
+ - `position` - Find the position in a string where an x coordinate falls.
+ - `split` - Find where to split a string to make it fit a width.
+
+# Worked Example
+
+Rather than attempt to describe every aspect of an implementation we
+will rather work from an actual minimal example for the FLTK toolkit.
+
+This is availble as a single commit (`git show
04900e82e65f8669675538a66a01b56a3e473cb2`) in the NetSurf source repository.
Alternatively it can be [viewed in a web
browser](https://git.netsurf-browser.org/netsurf.git/commit/?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2).
+
+This represents the absolute minimum implementation to get a browser
+window on screen (and be able to click visible links). It is
+implemented in C++ as that is the FLTK implementation language but an
+equivalent implementation in other languages should be obvious.
+
+## Building
+
+The
[frontends/Makefile.hts](https://git.netsurf-browser.org/netsurf.git/diff/frontends/Makefile.hts?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
+had the fltk target added to the VLDTARGET variable. This allows
+NetSurf to be built for this frontend with `make TARGET=fltk`
+
+As previously described the three GNU Make files are added:
+
+[Makefile](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
+this shows how the flags are extended to add the fltk headers and
+library. Additionaly the list of sources are built here, as teh
+comment suggests it is important the SOURCES variable is not expanded
+here so the S_FRONTEND variable is used to allow expansion at teh
+correct time in the build process.
+
+[Makefile.defaults](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile.defaults?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
+has the default setting to control the build parameters and file locations.
These can be overriden by the `Makefile.config` at compile time.
+
+[Makefile.tools](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile.tools?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
+allows the configuration of additional tools necessary to build for the target
as a minimum pkg-config is usually required to find libraries.
+
+## Program entry
+
+In our example program entry is the classical `main()` in the
[main.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/main.cpp?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
module.
+
+This implements the six stage process outlined previously.
+
+### Operations table registration
+
+The `netsurf_table` structure is initialised and passed to
+`netsurf_register()`. It should be noted that the approach taken here
+and in most frontends is to have a source module for each operation
+table. The header for each module exposes just the pointer to the
+indivial operation set, this allows for all the operation functions to
+be static to their module and hence helps reduce global symbol usage.
+
+### Frontend specific initialisation
+
+Her it is implemented in `nsfltk_init()` this function performs all
+the operations specific to the frontend which must be initialised
+before netsurf itself. In some toolkits this would require calling the
+toolkit initialisation (e.g. `gtk_init()`).
+
+It is nessesary to initialise netsurf logging and user options at this
+point. A more fully featured implementation would also initialise the
+message translation system here.
+
+### Netsurf initialisation
+
+This is simply the call to `netsurf_init()` from this point the
+browser is fully operational and operations can and will be called.
+
+### Frontend specific startup
+
+Although the browser is running it has not yet been told to open a
+window or navigate to a page. Here `nsfltk_start()` examines the
+command line and environment to determine the initial page to navigate
+to and calls `browser_window_create()` with the url, this will cause
+the browser to open a new browsing context and start the navigation.
+
+A frontend may choose to implement more complex logic here but the
+example here is a good start.
+
+### Toolkit run loop
+
+The function `nsfltk_run()` runs the toolkit event loop. In this case it is
using the generic scheduleing in the
[misc.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/misc.cpp?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
module to ensure callbacks get made at the apropriate time.
+
+There is a `nsfltk_done` boolean global checked here so when all the
+browser windows are closed the program will exit.
+
+A more fully featured port might use the toolkits scheduling rather
+than open coding a solution with a linked list as is done
+here.
+
+A futher optimisation would be to obtain the set of file descriptors
+being used (with `fetch_fdset()`) for active fetches allowing for
+activity based fetch progress instead of the fallback polling method.
+
+### finalisation
+
+This simply finalises the browser stopping all activity and cleaning
+up any resource usage. After the call to `netsurf_exit()` no more
+operation calls will be made and all caches used by the core will be
+flushed.
+
+If user option chnages are to be made persistant `nsoption_finalise()`
+should be called.
+
+The finalisation of logging will ensure that any output buffers are
+flushed.
+
+## The window operation table
+
+Amongst all the boilerplate of the default implementation the only novel code
is in the window operation table in the
[window.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/window.cpp?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
module.
+
+### `nsfltk_window_create`
+
+The create operation instansiates a new `NS_Window` object and
+references it in the gui_window structure which it returns to the
+caller. Technically we could simply return the `NS_Window` object as
+the gui_window pointer but this implementation is avoiding the cast.
+
+Secondly `Fl_Double_Window` is subclassed as `NS_Widget`. The sublass
+allows the close callback to be accessed so the global `nsfltk_done`
+boolean can be set during the destructor method.
+
+The NS_Window creates an instance of `NS_Widget` in its constructor, a
+more extensive implementation would add other window furniture here
+(scroll bars, url bar, navigation elements, etc.)
+
+The implementation subclasses `Fl_Widget` implementing the draw
+method to render the browsing context and the handle method to handle
+mouse events to allow teh user to click.
+
+The `NS_Widget::handle()` method simply translates the mouse press
+event from widget coordinates to netsurf canvas cooridinates and maps
+teh mouse button state. The core is informed of these events using
+`browser_window_mouse_click()`
+
+The `NS_Widget::draw` method similarly translates the fltk toolkits
+clip rectangle, builds a plotting context and calls
+`browser_window_redraw()` which will use the plotting operations in
+the plotting context to render the browsing context within the area
+specified. One thing to note here is the translation between the
+coordinates of the render area and the internal page canvas given as
+the second and third parameters to the draw call. When scrolling is
+required this is achived by altering these offsets.
+
+
+### `nsfltk_window_invalidate()`
+
+This simply calls the damage method on the `Fl_Widget` class with the
+appropriate coordinate translation.
+
+### `nsfltk_window_get_dimensions()`
+
+This obtains the fltk widget width and height and returns them.
+
+## The plotting interface
+
+When the `NS_Widget::draw` method was discussed it was noted that a
+plotting context is built containing an operation table. That table is
+implemented in
[plotters.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/plotters.cpp?h=vince/fltk&id=04900e82e65f8669675538a66a01b56a3e473cb2)
+
+The implementation here is as minimal as can be, only line, rectangle
+and text have any implementation at all and even that simply sets a
+colour and performs the appropriate fltk draw function (`fl_line`,
+`fl_rect` and `fl_draw` respectively)
+
+# Conclusion
+
+Hopefully this breif overview and worked example should give the
+prospectinve frontend developer enough information to understand how
+to get started implementing a new frontend toolkit for NetSurf.
+
+As can be seen there is actualy very little novel code necessary to
+get started though I should mention that the move from "minimal" to
+"full" implementation is a large undertaking and it would be wise to
+talk with the NetSurf developers if undertaking such work.
diff --git a/frontends/fltk/main.cpp b/frontends/fltk/main.cpp
index 935bd2a..ab0e1bc 100644
--- a/frontends/fltk/main.cpp
+++ b/frontends/fltk/main.cpp
@@ -169,9 +169,6 @@ static void nsfltk_run(void)
do {
/* run scheduled callbacks and get the next event delta in ms */
schedtm = nsfltk_schedule_run();
- if (schedtm > 0) {
- NSLOG(netsurf, INFO, "scheduling for %d", schedtm);
- }
Fl::wait(((double)schedtm/1000));
} while(nsfltk_done != true);
}
diff --git a/frontends/fltk/window.cpp b/frontends/fltk/window.cpp
index 19aa265..fffc380 100644
--- a/frontends/fltk/window.cpp
+++ b/frontends/fltk/window.cpp
@@ -24,11 +24,17 @@
#include <stddef.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Scrollbar.H>
#include <FL/fl_draw.H>
+#include <Fl/Fl_Output.H>
+#include <Fl/Fl_Pack.H>
+#include <Fl/Fl_Button.H>
extern "C" {
#include "utils/errors.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
#include "netsurf/types.h"
#include "netsurf/mouse.h"
#include "netsurf/window.h"
@@ -36,6 +42,7 @@ extern "C" {
#include "netsurf/content.h"
#include "netsurf/browser_window.h"
#include "netsurf/mouse.h"
+#include "desktop/browser_history.h"
}
@@ -44,10 +51,16 @@ extern "C" {
extern bool nsfltk_done;
+struct gui_window {
+ class NS_Window *window;
+};
+
class NS_Widget : public Fl_Widget
{
private:
- struct browser_window *mbw;
+ struct browser_window *m_bw;
+ int m_xoffset;
+ int m_yoffset;
protected:
void draw();
@@ -55,38 +68,19 @@ protected:
public:
NS_Widget(int X,int Y,int W,int H, struct browser_window *bw)
- : Fl_Widget(X,Y,W,H), mbw(bw) {}
-};
-
-
-class NS_Window : public Fl_Double_Window
-{
-private:
- struct browser_window *mbw;
- NS_Widget *mnswidget;
-
- void close_callback(Fl_Widget *w);
- static void static_close_callback(Fl_Widget *w, void *f) { ((NS_Window
*)f)->close_callback(w); }
+ : Fl_Widget(X,Y,W,H), m_bw(bw), m_xoffset(0), m_yoffset(0) {}
-public:
- NS_Window(int W, int H, struct browser_window *bw)
- : Fl_Double_Window(W,H), mbw(bw) {
- this->callback(static_close_callback, (void *)this);
- mnswidget = new NS_Widget(0, 0, W, H, bw);
- this->end();
- }
- ~NS_Window() { nsfltk_done=true; }
+ bool get_scroll(int *sx, int *sy);
+ nserror get_dimensions(int *width, int *height);
- NS_Widget *get_nswidget() { return mnswidget; }
+ nserror invalidate(const struct rect *rect);
+ void vscroll_callback(Fl_Scrollbar *w);
+ void hscroll_callback(Fl_Scrollbar *w);
};
-struct gui_window {
- struct browser_window *bw;
- NS_Window *window;
-};
/**
- * method to handle events on the netsurf browsing widget
+ * handle events on the netsurf browsing widget
*/
int NS_Widget::handle(int event)
{
@@ -99,10 +93,10 @@ int NS_Widget::handle(int event)
if (button == FL_LEFT_MOUSE) {
state |= BROWSER_MOUSE_PRESS_1;
}
- browser_window_mouse_click(mbw,
+ browser_window_mouse_click(m_bw,
(browser_mouse_state)state,
- Fl::event_x() - x(),
- Fl::event_y() - y());
+ Fl::event_x() - x() + m_xoffset,
+ Fl::event_y() - y() + m_yoffset);
return 1;
case FL_RELEASE:
@@ -111,10 +105,10 @@ int NS_Widget::handle(int event)
state |= BROWSER_MOUSE_CLICK_1;
}
- browser_window_mouse_click(mbw,
+ browser_window_mouse_click(m_bw,
(browser_mouse_state)state,
- Fl::event_x() - x(),
- Fl::event_y() - y());
+ Fl::event_x() - x() + m_xoffset,
+ Fl::event_y() - y() + m_yoffset);
return 1;
default:
@@ -124,7 +118,7 @@ int NS_Widget::handle(int event)
/**
- * method to redraw the netsurf browsing widget
+ * redraw the netsurf browsing widget
*/
void NS_Widget::draw()
{
@@ -140,103 +134,352 @@ void NS_Widget::draw()
.priv = NULL,
};
- browser_window_redraw(mbw, x(), y(), &clip, &ctx);
+ browser_window_redraw(m_bw,
+ x() - m_xoffset,
+ y() - m_yoffset,
+ &clip,
+ &ctx);
}
+
/**
- * callback when fltk window is closed
+ * vertical scrollbar position has been changed
*/
-void NS_Window::close_callback(Fl_Widget *w)
+void NS_Widget::vscroll_callback(Fl_Scrollbar *sb)
{
- browser_window_destroy(mbw);
+ m_yoffset = sb->value();
+ damage(FL_DAMAGE_SCROLL);
}
+
/**
- * Create and open a gui window for a browsing context.
- *
- * The implementing front end must create a context suitable
- * for it to display a window referred to as the "gui window".
- *
- * The frontend will be expected to request the core redraw
- * areas of the gui window which have become invalidated
- * either from toolkit expose events or as a result of a
- * invalidate() call.
- *
- * Most core operations used by the frontend concerning browser
- * windows require passing the browser window context therefor
- * the gui window must include a reference to the browser
- * window passed here.
- *
- * If GW_CREATE_CLONE flag is set existing is non-NULL.
- *
- * \param bw The core browsing context associated with the gui window
- * \param existing An existing gui_window, may be NULL.
- * \param flags flags to control the gui window creation.
- * \return gui window, or NULL on error.
+ * horizontal scrollbar position has been changed
*/
-static struct gui_window *
-nsfltk_window_create(struct browser_window *bw,
- struct gui_window *existing,
- gui_window_create_flags flags)
+void NS_Widget::hscroll_callback(Fl_Scrollbar *sb)
{
- struct gui_window *gw;
- gw = (struct gui_window *)calloc(1, sizeof(struct gui_window));
-
- gw->window = new NS_Window(800,600, bw);
+ m_xoffset = sb->value();
+ damage(FL_DAMAGE_SCROLL);
+}
- gw->window->show();
+/**
+ * get the current scroll offsets
+ */
+bool NS_Widget::get_scroll(int *sx, int *sy)
+{
+ *sx = m_xoffset;
+ *sy = m_yoffset;
- return gw;
+ return true;
}
+
/**
- * Destroy previously created gui window
- *
- * \param gw The gui window to destroy.
+ * get the viewable dimensions of browsing context
*/
-static void nsfltk_window_destroy(struct gui_window *gw)
+nserror NS_Widget::get_dimensions(int *width, int *height)
{
- Fl::delete_widget(gw->window);
- free(gw);
+ *width = w();
+ *height = h();
+
+ return NSERROR_OK;
}
/**
- * Invalidate an area of a window.
- *
- * The specified area of the window should now be considered
- * out of date. If the area is NULL the entire window must be
- * invalidated. It is expected that the windowing system will
- * then subsequently cause redraw/expose operations as
- * necessary.
- *
- * \note the frontend should not attempt to actually start the
- * redraw operations as a result of this callback because the
- * core redraw functions may already be threaded.
- *
- * \param gw The gui window to invalidate.
- * \param rect area to redraw or NULL for the entire window area
- * \return NSERROR_OK on success or appropriate error code
+ * mark an area of the browsing context as invalid
*/
-static nserror
-nsfltk_window_invalidate(struct gui_window *gw, const struct rect *rect)
+nserror NS_Widget::invalidate(const struct rect *rect)
{
- NS_Widget *nswidget;
- nswidget = gw->window->get_nswidget();
-
if (rect == NULL) {
- nswidget->damage(FL_DAMAGE_ALL);
+ damage(FL_DAMAGE_ALL);
+ } else {
+ damage(FL_DAMAGE_ALL,
+ rect->x0,
+ rect->y0,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
+ }
+ return NSERROR_OK;
+
+}
+
+/**
+ * widget representing url bar
+ */
+class NS_URLBar : public Fl_Pack
+{
+private:
+ struct browser_window *m_bw;
+ Fl_Button *m_back_button;
+ Fl_Button *m_forward_button;
+ Fl_Input *m_input;
+
+ void back_callback(Fl_Button *button);
+ void forward_callback(Fl_Button *button);
+public:
+ NS_URLBar(int X,int Y,int W,int H, struct browser_window *bw);
+ nserror set_url(struct nsurl *url);
+
+ /* static wrapper for fltk callbacks */
+ static void static_back_callback(Fl_Widget *w, void *f);
+ static void static_forward_callback(Fl_Widget *w, void *f);
+
+};
+
+NS_URLBar::NS_URLBar(int X,int Y,int W,int H, struct browser_window *bw)
+ : Fl_Pack(X,Y,W,H), m_bw(bw)
+{
+ type(Fl_Pack::HORIZONTAL);
+ spacing(4);
+
+ m_back_button = new Fl_Button(0,0,H,H, "B");
+ m_back_button->callback(static_back_callback, (void *)this);
+
+ m_forward_button = new Fl_Button(0,0,H,H, "F");
+ m_forward_button->callback(static_forward_callback, (void *)this);
+
+ m_input = new Fl_Input(0,0,W,H);
+
+ end();
+
+ resizable(m_input);
+}
+
+nserror NS_URLBar::set_url(struct nsurl *url)
+{
+ size_t idn_url_l;
+ char *idn_url_s = NULL;
+ if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) == NSERROR_OK) {
+ m_input->value(idn_url_s, idn_url_l-1);
+ free(idn_url_s);
} else {
- nswidget->damage(FL_DAMAGE_ALL,
- rect->x0,
- rect->y0,
- rect->x1 - rect->x0,
- rect->y1 - rect->y0);
+ m_input->value(nsurl_access(url));
}
return NSERROR_OK;
}
+void NS_URLBar::back_callback(Fl_Button *button)
+{
+ browser_window_history_back(m_bw, false);
+}
+
+void NS_URLBar::forward_callback(Fl_Button *button)
+{
+ browser_window_history_forward(m_bw, false);
+}
+
+
+void NS_URLBar::static_back_callback(Fl_Widget *w, void *f)
+{
+ ((NS_URLBar *)f)->back_callback((Fl_Button *)w);
+}
+
+void NS_URLBar::static_forward_callback(Fl_Widget *w, void *f)
+{
+ ((NS_URLBar *)f)->forward_callback((Fl_Button *)w);
+}
+
+
+/**
+ * Class for netsurf window
+ */
+class NS_Window : public Fl_Double_Window
+{
+private:
+ struct browser_window *m_bw;
+
+ NS_URLBar *m_nsurlbar;
+ NS_Widget *m_nswidget;
+ Fl_Scrollbar *m_vscrollbar;
+ Fl_Scrollbar *m_hscrollbar;
+ Fl_Output *m_status;
+
+ nserror set_scroll(const struct rect *rect);
+ void set_status(const char *text);
+ void set_title(const char *title);
+ nserror set_extent(int w, int h);
+
+ void close_callback(Fl_Widget *w);
+
+ /* static wrapper for fltk callbacks */
+ static void static_close_callback(Fl_Widget *w, void *f);
+ static void static_hscroll_callback(Fl_Widget *w, void *f);
+ static void static_vscroll_callback(Fl_Widget *w, void *f);
+
+public:
+ NS_Window(int W, int H, struct browser_window *bw);
+ ~NS_Window() { nsfltk_done=true; }
+
+ /* static wrappers to be able to call instance methods */
+ static nserror static_set_scroll(struct gui_window *gw, const struct
rect *rect);
+ static void static_set_status(struct gui_window *gw, const char *text);
+ static void static_set_title(struct gui_window *gw, const char *title);
+
+ static bool static_get_scroll(struct gui_window *gw, int *sx, int *sy);
+ static nserror static_set_url(struct gui_window *gw, struct nsurl *url);
+
+ static nserror static_event(struct gui_window *gw, enum
gui_window_event event);
+ static nserror static_invalidate(struct gui_window *gw, const struct
rect *rect);
+ static nserror static_get_dimensions(struct gui_window *gw, int *width,
int *height);
+ static struct gui_window *static_create(struct browser_window *bw,
struct gui_window *existing, gui_window_create_flags flags);
+ static void static_destroy(struct gui_window *gw);
+};
+
+
+/**
+ * netsurf window class constructor
+ */
+NS_Window::NS_Window(int W, int H, struct browser_window *bw)
+ : Fl_Double_Window(W,H), m_bw(bw)
+{
+ int scrlsize = Fl::scrollbar_size();
+ int splitx = (nsoption_int(toolbar_status_size) * W) / 10000;
+ int urlbarh = scrlsize * 2;
+
+ callback(static_close_callback, (void *)this);
+
+ // url bar
+ m_nsurlbar = new NS_URLBar(0, 0, W, urlbarh, bw);
+
+ // browser drawing canvas widget
+ m_nswidget = new NS_Widget(0,
+ m_nsurlbar->h(),
+ W - scrlsize,
+ H - scrlsize - urlbarh,
+ bw);
+
+ // vertical scrollbar
+ m_vscrollbar = new Fl_Scrollbar(m_nswidget->w(),
+ m_nsurlbar->h(),
+ scrlsize,
+ m_nswidget->h());
+ m_vscrollbar->callback(static_vscroll_callback, (void *)m_nswidget);
+ m_vscrollbar->value(0, m_nswidget->h(), 0, m_nswidget->h());
+
+ // horizontal scrollbar
+ m_hscrollbar = new Fl_Scrollbar(splitx,
+ m_nswidget->y() + m_nswidget->h(),
+ m_nswidget->w() - splitx,
+ scrlsize);
+ m_hscrollbar->type(FL_HORIZONTAL);
+ m_hscrollbar->callback(static_hscroll_callback, (void *)m_nswidget);
+ m_hscrollbar->value(0, m_nswidget->w(), 0, m_nswidget->w());
+
+ // status text
+ m_status = new Fl_Output(0, m_hscrollbar->y(), splitx, scrlsize);
+ end();
+
+ resizable(m_nswidget);
+}
+
+
+/**
+ * fltk window has been closed
+ */
+void NS_Window::close_callback(Fl_Widget *w)
+{
+ browser_window_destroy(m_bw);
+}
+
+
+
+
+/**
+ * set the status text
+ */
+void NS_Window::set_status(const char *text)
+{
+ m_status->value(text);
+}
+
+
+/**
+ * set the window title text
+ */
+void NS_Window::set_title(const char *text)
+{
+ label(text);
+}
+
+
+/**
+ * set the current position of the scroll bars
+ */
+nserror NS_Window::set_scroll(const struct rect *rect)
+{
+ m_vscrollbar->value(rect->y0);
+ m_hscrollbar->value(rect->x0);
+
+ m_nswidget->vscroll_callback(m_vscrollbar);
+ m_nswidget->hscroll_callback(m_hscrollbar);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Set the extent of the underlying canvas
+ */
+nserror NS_Window::set_extent(int ew, int eh)
+{
+ m_hscrollbar->value(0, w(), 0, ew);
+ m_vscrollbar->value(0, h(), 0, eh);
+
+ return NSERROR_OK;
+}
+
+
+/* static methods */
+
+/**
+ * static window close fltk callback which calls the instance
+ */
+void NS_Window::static_close_callback(Fl_Widget *w, void *f)
+{
+ ((NS_Window *)f)->close_callback(w);
+}
+
+/**
+ * static vertical scrollbar fltk callback which calls the instance
+ */
+void NS_Window::static_vscroll_callback(Fl_Widget *w, void *f)
+{
+ ((NS_Widget *)f)->vscroll_callback((Fl_Scrollbar *)w);
+}
+
+/**
+ * static horizontal scrollbar fltk callback which calls the instance
+ */
+void NS_Window::static_hscroll_callback(Fl_Widget *w, void *f)
+{
+ ((NS_Widget *)f)->hscroll_callback((Fl_Scrollbar *)w);
+}
+
+
+/**
+ * Set the status bar message of a browser window.
+ *
+ * \param g gui_window to update
+ * \param text new status text
+ */
+void NS_Window::static_set_status(struct gui_window *gw, const char *text)
+{
+ ((NS_Window *)gw->window)->set_status(text);
+}
+
+
+/**
+ * Set the title of a window.
+ *
+ * \param gw The gui window to set title of.
+ * \param title new window title
+ */
+void NS_Window::static_set_title(struct gui_window *gw, const char *title)
+{
+ ((NS_Window *)gw->window)->set_title(title);
+}
+
/**
* Get the scroll position of a browser window.
@@ -246,17 +489,17 @@ nsfltk_window_invalidate(struct gui_window *gw, const
struct rect *rect)
* \param sy receives y ordinate of point at top-left of window
* \return true iff successful
*/
-static bool nsfltk_window_get_scroll(struct gui_window *gw, int *sx, int *sy)
+bool NS_Window::static_get_scroll(struct gui_window *gw, int *sx, int *sy)
{
- return false;
+ return gw->window->m_nswidget->get_scroll(sx, sy);
}
/**
* Set the scroll position of a browser window.
*
- * scrolls the viewport to ensure the specified rectangle of
- * the content is shown.
+ * scrolls the viewport to ensure the specified rectangle of the
+ * content is shown.
* If the rectangle is of zero size i.e. x0 == x1 and y0 == y1
* the contents will be scrolled so the specified point in the
* content is at the top of the viewport.
@@ -268,10 +511,80 @@ static bool nsfltk_window_get_scroll(struct gui_window
*gw, int *sx, int *sy)
* \param rect The rectangle to ensure is shown.
* \return NSERROR_OK on success or appropriate error code.
*/
-static nserror
-nsfltk_window_set_scroll(struct gui_window *gw, const struct rect *rect)
+nserror
+NS_Window::static_set_scroll(struct gui_window *gw, const struct rect *rect)
{
- return NSERROR_OK;
+ return gw->window->set_scroll(rect);
+}
+
+
+/**
+ * Set the navigation url.
+ *
+ * \param gw window to update.
+ * \param url The url to use as icon.
+ */
+nserror NS_Window::static_set_url(struct gui_window *gw, struct nsurl *url)
+{
+ return gw->window->m_nsurlbar->set_url(url);
+}
+
+
+/**
+ * Miscellaneous event occurred for a window
+ *
+ * This is used to inform the frontend of window events which
+ * require no additional parameters.
+ *
+ * \param gw The gui window the event occurred for
+ * \param event Which event has occurred.
+ * \return NSERROR_OK if the event was processed else error code.
+ */
+nserror
+NS_Window::static_event(struct gui_window *gw, enum gui_window_event event)
+{
+ nserror res;
+
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ {
+ int w, h;
+
+ res = browser_window_get_extents(gw->window->m_bw, true, &w,
&h);
+ if (res == NSERROR_OK) {
+ res = (gw->window)->set_extent(w, h);
+ }
+ break;
+ }
+ default:
+ res = NSERROR_OK;
+ break;
+ }
+ return res;
+}
+
+
+/**
+ * Invalidate an area of a window.
+ *
+ * The specified area of the window should now be considered
+ * out of date. If the area is NULL the entire window must be
+ * invalidated. It is expected that the windowing system will
+ * then subsequently cause redraw/expose operations as
+ * necessary.
+ *
+ * \note the frontend should not attempt to actually start the
+ * redraw operations as a result of this callback because the
+ * core redraw functions may already be threaded.
+ *
+ * \param gw The gui window to invalidate.
+ * \param rect area to redraw or NULL for the entire window area
+ * \return NSERROR_OK on success or appropriate error code
+ */
+nserror
+NS_Window::static_invalidate(struct gui_window *gw, const struct rect *rect)
+{
+ return gw->window->m_nswidget->invalidate(rect);
}
@@ -289,47 +602,80 @@ nsfltk_window_set_scroll(struct gui_window *gw, const
struct rect *rect)
* \return NSERROR_OK on success and width and height updated
* else error code.
*/
-static nserror
-nsfltk_window_get_dimensions(struct gui_window *gw, int *width, int *height)
+nserror
+NS_Window::static_get_dimensions(struct gui_window *gw, int *width, int
*height)
{
- NS_Widget *nswidget;
- nswidget = gw->window->get_nswidget();
-
- *width = nswidget->w();
- *height = nswidget->h();
-
- return NSERROR_OK;
+ return gw->window->m_nswidget->get_dimensions(width, height);
}
/**
- * Miscellaneous event occurred for a window
+ * Create and open a gui window for a browsing context.
*
- * This is used to inform the frontend of window events which
- * require no additional parameters.
+ * The implementing front end must create a context suitable
+ * for it to display a window referred to as the "gui window".
*
- * \param gw The gui window the event occurred for
- * \param event Which event has occurred.
- * \return NSERROR_OK if the event was processed else error code.
+ * The frontend will be expected to request the core redraw
+ * areas of the gui window which have become invalidated
+ * either from toolkit expose events or as a result of a
+ * invalidate() call.
+ *
+ * Most core operations used by the frontend concerning browser
+ * windows require passing the browser window context therefor
+ * the gui window must include a reference to the browser
+ * window passed here.
+ *
+ * If GW_CREATE_CLONE flag is set existing is non-NULL.
+ *
+ * \param bw The core browsing context associated with the gui window
+ * \param existing An existing gui_window, may be NULL.
+ * \param flags flags to control the gui window creation.
+ * \return gui window, or NULL on error.
*/
-static nserror
-nsfltk_window_event(struct gui_window *gw, enum gui_window_event event)
+struct gui_window *
+NS_Window::static_create(struct browser_window *bw,
+ struct gui_window *existing,
+ gui_window_create_flags flags)
{
- return NSERROR_OK;
+ struct gui_window *gw;
+ gw = (struct gui_window *)calloc(1, sizeof(struct gui_window));
+
+ if (gw != NULL) {
+ gw->window = new NS_Window(800,600, bw);
+
+ gw->window->show();
+ }
+
+ return gw;
}
+/**
+ * Destroy previously created gui window
+ *
+ * \param gw The gui window to destroy.
+ */
+void NS_Window::static_destroy(struct gui_window *gw)
+{
+ Fl::delete_widget(gw->window);
+ free(gw);
+}
+
+
+/**
+ * window operations table for fltk frontend
+ */
static struct gui_window_table window_table = {
- .create = nsfltk_window_create,
- .destroy = nsfltk_window_destroy,
- .invalidate = nsfltk_window_invalidate,
- .get_scroll = nsfltk_window_get_scroll,
- .set_scroll = nsfltk_window_set_scroll,
- .get_dimensions = nsfltk_window_get_dimensions,
- .event = nsfltk_window_event,
- .set_title = NULL,
- .set_url = NULL,
+ .create = NS_Window::static_create,
+ .destroy = NS_Window::static_destroy,
+ .invalidate = NS_Window::static_invalidate,
+ .get_scroll = NS_Window::static_get_scroll,
+ .set_scroll = NS_Window::static_set_scroll,
+ .get_dimensions = NS_Window::static_get_dimensions,
+ .event = NS_Window::static_event,
+ .set_title = NS_Window::static_set_title,
+ .set_url = NS_Window::static_set_url,
.set_icon = NULL,
- .set_status = NULL,
+ .set_status = NS_Window::static_set_status,
.set_pointer = NULL,
.place_caret = NULL,
.drag_start = NULL,
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]