/* * Copyright 2021 Vincent Sanders * * 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 . */ /** * \file * Implementation of netsurf window (widget) for fltk. */ #include #include #include #include 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;