summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2021-03-23 22:07:34 +0000
committerVincent Sanders <vince@kyllikki.org>2021-03-23 22:12:21 +0000
commitbc546388ce428be5cfa37cecb174d549c7b30320 (patch)
tree23a039aea62456ebb56876aba50368f05c2fa420
parent28ecbf82ed3024f51be4c87928fd91bacfc15cbc (diff)
downloadnetsurf-vince/fltk.tar.gz
netsurf-vince/fltk.tar.bz2
greatly improve fltk browser user interfacevince/fltk
-rw-r--r--frontends/fltk/window.cpp618
1 files changed, 482 insertions, 136 deletions
diff --git a/frontends/fltk/window.cpp b/frontends/fltk/window.cpp
index 19aa26556..fffc38064 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,