summaryrefslogtreecommitdiff
path: root/framebuffer
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2014-07-26 22:12:55 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2014-07-26 22:12:55 +0100
commit31def6a33878b1ca8f5340d30708c853cdafefa1 (patch)
treee8ec8b84db672163a1a01ee93937adefe6b1cc57 /framebuffer
parent989e82544e3a5b2f74216e91d269e3572c8053ce (diff)
downloadnetsurf-31def6a33878b1ca8f5340d30708c853cdafefa1.tar.gz
netsurf-31def6a33878b1ca8f5340d30708c853cdafefa1.tar.bz2
Add rudimentary support for resizing.
- Currently only libnsfb's SDL surface supports resizing. - Flickers like crazy while resizing. Possibly because the SDL surface is not set to use double buffering. - The internal widget library, fbtk, was never intended for this, as such it has no knowledge of how a widget should be positioned with respect to its parent. This means the top level window has to track everything and move them itself.
Diffstat (limited to 'framebuffer')
-rw-r--r--framebuffer/fbtk.h23
-rw-r--r--framebuffer/fbtk/event.c7
-rw-r--r--framebuffer/fbtk/fbtk.c27
-rw-r--r--framebuffer/fbtk/scroll.c41
-rw-r--r--framebuffer/framebuffer.c85
-rw-r--r--framebuffer/framebuffer.h1
-rw-r--r--framebuffer/gui.c272
-rw-r--r--framebuffer/gui.h12
8 files changed, 435 insertions, 33 deletions
diff --git a/framebuffer/fbtk.h b/framebuffer/fbtk.h
index 325db0e9b..aff281439 100644
--- a/framebuffer/fbtk.h
+++ b/framebuffer/fbtk.h
@@ -270,7 +270,7 @@ bool fbtk_get_caret(fbtk_widget_t *widget, int *x, int *y, int *height);
/******************* Widget Manipulation **********************/
-/** Change the widget's position and size.
+/** Change the widget's position and size. (Doesn't redraw)
*
*/
bool fbtk_set_pos_and_size(fbtk_widget_t *widget, int x, int y, int width, int height);
@@ -369,6 +369,27 @@ bool fbtk_set_scroll_parameters(fbtk_widget_t *widget, int min, int max, int thu
bool fbtk_set_scroll_position(fbtk_widget_t *widget, int pos);
+/** Move and/or resize a horizontal scroll widget
+ *
+ * @param vscroll the horizontal scroll widget
+ * @param x new x pos
+ * @param y new y pos
+ * @param width new width
+ * @param height new height
+ */
+void fbtk_reposition_hscroll(fbtk_widget_t *scrollh,
+ int x, int y, int width, int height);
+
+/** Move and/or resize a vertical scroll widget
+ *
+ * @param vscroll the vertical scroll widget
+ * @param x new x pos
+ * @param y new y pos
+ * @param width new width
+ * @param height new height
+ */
+void fbtk_reposition_vscroll(fbtk_widget_t *scrollv,
+ int x, int y, int width, int height);
diff --git a/framebuffer/fbtk/event.c b/framebuffer/fbtk/event.c
index bd018c52c..2ef36321e 100644
--- a/framebuffer/fbtk/event.c
+++ b/framebuffer/fbtk/event.c
@@ -248,6 +248,13 @@ fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout)
timeout = 0;
break;
+ case NSFB_EVENT_RESIZE:
+ /* Try to resize framebuffer */
+ gui_resize(root,
+ event->value.resize.w,
+ event->value.resize.h);
+ break;
+
default:
break;
}
diff --git a/framebuffer/fbtk/fbtk.c b/framebuffer/fbtk/fbtk.c
index 984748402..cb8aec57f 100644
--- a/framebuffer/fbtk/fbtk.c
+++ b/framebuffer/fbtk/fbtk.c
@@ -209,6 +209,29 @@ fbtk_set_pos_and_size(fbtk_widget_t *widget,
int x, int y,
int width, int height)
{
+ if (widget->parent != NULL) {
+ fbtk_widget_t *parent = widget->parent;
+
+ /* make new window fit inside parent */
+ if (width == 0) {
+ width = parent->width - x;
+ } else if (width < 0) {
+ width = parent->width + width - x;
+ }
+ if ((width + x) > parent->width) {
+ width = parent->width - x;
+ }
+
+ if (height == 0) {
+ height = parent->height - y;
+ } else if (height < 0) {
+ height = parent->height + height - y;
+ }
+ if ((height + y) > parent->height) {
+ height = parent->height - y;
+ }
+ }
+
if ((widget->x != x) ||
(widget->y != y) ||
(widget->width != width) ||
@@ -217,10 +240,6 @@ fbtk_set_pos_and_size(fbtk_widget_t *widget,
widget->y = y;
widget->width = width;
widget->height = height;
- /* @todo This should limit the redrawn area to the sum
- * of the old and new widget dimensions, not redraw the lot.
- */
- fbtk_request_redraw(widget->parent);
return true;
}
return false;
diff --git a/framebuffer/fbtk/scroll.c b/framebuffer/fbtk/scroll.c
index 0ce56a6ee..e91c3ef6e 100644
--- a/framebuffer/fbtk/scroll.c
+++ b/framebuffer/fbtk/scroll.c
@@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <assert.h>
+
#include <stdbool.h>
#include <libnsfb.h>
@@ -272,6 +274,26 @@ fbtk_create_vscroll(fbtk_widget_t *parent,
return neww;
}
+
+/* exported function documented in fbtk.h */
+void
+fbtk_reposition_vscroll(fbtk_widget_t *vscroll,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ assert(vscroll->type == FB_WIDGET_TYPE_VSCROLL);
+
+ fbtk_set_pos_and_size(vscroll, x, y + scrollu.height,
+ width, height - scrollu.height - scrolld.height);
+ fbtk_set_pos_and_size(vscroll->u.scroll.btnul,
+ x, y, width, scrollu.height);
+ fbtk_set_pos_and_size(vscroll->u.scroll.btndr,
+ x, y + height - scrolld.height,
+ width, scrolld.height);
+}
+
/* Horizontal scroll widget */
static int
@@ -488,6 +510,25 @@ fbtk_create_hscroll(fbtk_widget_t *parent,
return neww;
}
+/* exported function documented in fbtk.h */
+void
+fbtk_reposition_hscroll(fbtk_widget_t *scrollh,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ assert(scrollh->type == FB_WIDGET_TYPE_HSCROLL);
+
+ fbtk_set_pos_and_size(scrollh, x + scrolll.width, y,
+ width - scrolll.width - scrollr.width, height);
+ fbtk_set_pos_and_size(scrollh->u.scroll.btnul,
+ x, y, scrolll.width, height);
+ fbtk_set_pos_and_size(scrollh->u.scroll.btndr,
+ x + width - scrollr.width, y,
+ scrollr.width, height);
+}
+
/* exported function documented in fbtk.h */
bool
diff --git a/framebuffer/framebuffer.c b/framebuffer/framebuffer.c
index 4cd064c34..1b0c34b54 100644
--- a/framebuffer/framebuffer.c
+++ b/framebuffer/framebuffer.c
@@ -341,6 +341,42 @@ const struct plotter_table fb_plotters = {
};
+static bool framebuffer_format_from_bpp(int bpp, enum nsfb_format_e *fmt)
+{
+ switch (bpp) {
+ case 32:
+ *fmt = NSFB_FMT_XRGB8888;
+ break;
+
+ case 24:
+ *fmt = NSFB_FMT_RGB888;
+ break;
+
+ case 16:
+ *fmt = NSFB_FMT_RGB565;
+ break;
+
+ case 8:
+ *fmt = NSFB_FMT_I8;
+ break;
+
+ case 4:
+ *fmt = NSFB_FMT_I4;
+ break;
+
+ case 1:
+ *fmt = NSFB_FMT_I1;
+ break;
+
+ default:
+ LOG(("Bad bits per pixel (%d)\n", bpp));
+ return false;
+ }
+
+ return true;
+}
+
+
nsfb_t *
framebuffer_initialise(const char *fename, int width, int height, int bpp)
@@ -349,34 +385,8 @@ framebuffer_initialise(const char *fename, int width, int height, int bpp)
enum nsfb_format_e fbfmt;
/* bpp is a proxy for the framebuffer format */
- switch (bpp) {
- case 32:
- fbfmt = NSFB_FMT_XRGB8888;
- break;
-
- case 24:
- fbfmt = NSFB_FMT_RGB888;
- break;
-
- case 16:
- fbfmt = NSFB_FMT_RGB565;
- break;
-
- case 8:
- fbfmt = NSFB_FMT_I8;
- break;
-
- case 4:
- fbfmt = NSFB_FMT_I4;
- break;
-
- case 1:
- fbfmt = NSFB_FMT_I1;
- break;
-
- default:
- LOG(("Bad bits per pixel (%d)\n", bpp));
- return NULL;
+ if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
+ return NULL;
}
fbtype = nsfb_type_from_name(fename);
@@ -409,6 +419,25 @@ framebuffer_initialise(const char *fename, int width, int height, int bpp)
}
+bool
+framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
+{
+ enum nsfb_format_e fbfmt;
+
+ /* bpp is a proxy for the framebuffer format */
+ if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
+ return false;
+ }
+
+ if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
+ LOG(("Unable to change surface geometry\n"));
+ return false;
+ }
+
+ return true;
+
+}
+
void
framebuffer_finalise(void)
{
diff --git a/framebuffer/framebuffer.h b/framebuffer/framebuffer.h
index 0e46cb1f5..5204dbd92 100644
--- a/framebuffer/framebuffer.h
+++ b/framebuffer/framebuffer.h
@@ -3,6 +3,7 @@
extern const struct plotter_table fb_plotters;
nsfb_t *framebuffer_initialise(const char *fename, int width, int height, int bpp);
+bool framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp);
void framebuffer_finalise(void);
bool framebuffer_set_cursor(struct fbtk_bitmap *bm);
diff --git a/framebuffer/gui.c b/framebuffer/gui.c
index f77edc46e..5590a66e9 100644
--- a/framebuffer/gui.c
+++ b/framebuffer/gui.c
@@ -1229,6 +1229,7 @@ create_toolbar(struct gui_window *gw,
&history_image,
fb_localhistory_btn_clik,
gw);
+ gw->history = widget;
break;
case 'f': /* forward */
@@ -1256,6 +1257,7 @@ create_toolbar(struct gui_window *gw,
&stop_image_g,
fb_close_click,
gw->bw);
+ gw->close = widget;
break;
case 's': /* stop */
@@ -1269,6 +1271,7 @@ create_toolbar(struct gui_window *gw,
&stop_image,
fb_stop_click,
gw->bw);
+ gw->stop = widget;
break;
case 'r': /* reload */
@@ -1282,6 +1285,7 @@ create_toolbar(struct gui_window *gw,
&reload,
fb_reload_click,
gw->bw);
+ gw->reload = widget;
break;
case 't': /* throbber/activity indicator */
@@ -1356,6 +1360,155 @@ create_toolbar(struct gui_window *gw,
return toolbar;
}
+
+/** Resize a toolbar.
+ *
+ * @param gw Parent window
+ * @param toolbar_height The height in pixels of the toolbar
+ * @param padding The padding in pixels round each element of the toolbar
+ * @param toolbar_layout A string defining which buttons and controls
+ * should be added to the toolbar. May be empty
+ * string to disable the bar.
+ */
+static void
+resize_toolbar(struct gui_window *gw,
+ int toolbar_height,
+ int padding,
+ const char *toolbar_layout)
+{
+ fbtk_widget_t *widget;
+
+ int xpos; /* The position of the next widget. */
+ int xlhs = 0; /* extent of the left hand side widgets */
+ int xdir = 1; /* the direction of movement + or - 1 */
+ const char *itmtype; /* type of the next item */
+ int x = 0, y = 0, w = 0, h = 0;
+
+ if (gw->toolbar == NULL) {
+ return;
+ }
+
+ if (toolbar_layout == NULL) {
+ toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT;
+ }
+
+ itmtype = toolbar_layout;
+
+ if (*itmtype == 0) {
+ return;
+ }
+
+ fbtk_set_pos_and_size(gw->toolbar, 0, 0, 0, toolbar_height);
+
+ xpos = padding;
+
+ /* loop proceeds creating widget on the left hand side until
+ * it runs out of layout or encounters a url bar declaration
+ * wherupon it works backwards from the end of the layout
+ * untill the space left is for the url bar
+ */
+ while (itmtype >= toolbar_layout && xdir != 0) {
+
+ switch (*itmtype) {
+ case 'b': /* back */
+ widget = gw->back;
+ x = (xdir == 1) ? xpos : xpos - left_arrow.width;
+ y = padding;
+ w = left_arrow.width;
+ h = -padding;
+ break;
+
+ case 'l': /* local history */
+ widget = gw->history;
+ x = (xdir == 1) ? xpos : xpos - history_image.width;
+ y = padding;
+ w = history_image.width;
+ h = -padding;
+ break;
+
+ case 'f': /* forward */
+ widget = gw->forward;
+ x = (xdir == 1) ? xpos : xpos - right_arrow.width;
+ y = padding;
+ w = right_arrow.width;
+ h = -padding;
+ break;
+
+ case 'c': /* close the current window */
+ widget = gw->close;
+ x = (xdir == 1) ? xpos : xpos - stop_image_g.width;
+ y = padding;
+ w = stop_image_g.width;
+ h = -padding;
+ break;
+
+ case 's': /* stop */
+ widget = gw->stop;
+ x = (xdir == 1) ? xpos : xpos - stop_image.width;
+ y = padding;
+ w = stop_image.width;
+ h = -padding;
+ break;
+
+ case 'r': /* reload */
+ widget = gw->reload;
+ x = (xdir == 1) ? xpos : xpos - reload.width;
+ y = padding;
+ w = reload.width;
+ h = -padding;
+ break;
+
+ case 't': /* throbber/activity indicator */
+ widget = gw->throbber;
+ x = (xdir == 1) ? xpos : xpos - throbber0.width;
+ y = padding;
+ w = throbber0.width;
+ h = -padding;
+ break;
+
+
+ case 'u': /* url bar*/
+ if (xdir == -1) {
+ /* met the u going backwards add url
+ * now we know available extent
+ */
+ widget = gw->url;
+ x = xlhs;
+ y = padding;
+ w = xpos - xlhs;
+ h = -padding;
+
+ /* toolbar is complete */
+ xdir = 0;
+ break;
+ }
+ /* met url going forwards, note position and
+ * reverse direction
+ */
+ itmtype = toolbar_layout + strlen(toolbar_layout);
+ xdir = -1;
+ xlhs = xpos;
+ w = fbtk_get_width(gw->toolbar);
+ xpos = 2 * w;
+ widget = gw->toolbar;
+ break;
+
+ default:
+ widget = NULL;
+ break;
+
+ }
+
+ if (widget != NULL) {
+ if (widget != gw->toolbar)
+ fbtk_set_pos_and_size(widget, x, y, w, h);
+ xpos += xdir * (w + padding);
+ }
+
+ itmtype += xdir;
+ }
+}
+
/** Routine called when "stripped of focus" event occours for browser widget.
*
* @param widget The widget reciving "stripped of focus" event.
@@ -1392,6 +1545,14 @@ create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_w
}
static void
+resize_browser_widget(struct gui_window *gw, int x, int y,
+ int width, int height)
+{
+ fbtk_set_pos_and_size(gw->browser, x, y, width, height);
+ browser_window_reformat(gw->bw, false, width, height);
+}
+
+static void
create_normal_browser_window(struct gui_window *gw, int furniture_width)
{
fbtk_widget_t *widget;
@@ -1412,6 +1573,7 @@ create_normal_browser_window(struct gui_window *gw, int furniture_width)
2,
FB_FRAME_COLOUR,
nsoption_charp(fb_toolbar_layout));
+ gw->toolbar = toolbar;
/* set the actually created toolbar height */
if (toolbar != NULL) {
@@ -1473,6 +1635,8 @@ create_normal_browser_window(struct gui_window *gw, int furniture_width)
fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL);
}
+ gw->bottom_right = widget;
+
/* create vertical scrollbar */
gw->vscroll = fbtk_create_vscroll(gw->window,
fbtk_get_width(gw->window) - furniture_width,
@@ -1491,6 +1655,81 @@ create_normal_browser_window(struct gui_window *gw, int furniture_width)
fbtk_set_focus(gw->browser);
}
+static void
+resize_normal_browser_window(struct gui_window *gw, int furniture_width)
+{
+ bool resized;
+ int width, height;
+ int toolbar_height = fbtk_get_height(gw->toolbar);
+ int statusbar_width = nsoption_int(toolbar_status_size) *
+ width / 10000;
+
+ /* Resize the main window widget */
+ resized = fbtk_set_pos_and_size(gw->window, 0, 0, 0, 0);
+ if (!resized)
+ return;
+
+ width = fbtk_get_width(gw->window);
+ height = fbtk_get_height(gw->window);
+
+ resize_toolbar(gw, toolbar_height, 2,
+ nsoption_charp(fb_toolbar_layout));
+ fbtk_set_pos_and_size(gw->status,
+ 0, height - furniture_width,
+ statusbar_width, furniture_width);
+ fbtk_reposition_hscroll(gw->hscroll,
+ statusbar_width, height - furniture_width,
+ width - statusbar_width - furniture_width,
+ furniture_width);
+ fbtk_set_pos_and_size(gw->bottom_right,
+ width - furniture_width, height - furniture_width,
+ furniture_width, furniture_width);
+ fbtk_reposition_vscroll(gw->vscroll,
+ width - furniture_width,
+ toolbar_height, furniture_width,
+ height - toolbar_height - furniture_width);
+ resize_browser_widget(gw,
+ 0, toolbar_height,
+ width - furniture_width,
+ height - furniture_width - toolbar_height);
+}
+
+static void gui_window_add_to_window_list(struct gui_window *gw)
+{
+ gw->next = NULL;
+ gw->prev = NULL;
+
+ if (window_list == NULL) {
+ window_list = gw;
+ } else {
+ window_list->prev = gw;
+ gw->next = window_list;
+ window_list = gw;
+ }
+}
+
+static void gui_window_remove_from_window_list(struct gui_window *gw)
+{
+ struct gui_window *list;
+
+ for (list = window_list; list != NULL; list = list->next) {
+ if (list != gw)
+ continue;
+
+ if (list == window_list) {
+ window_list = list->next;
+ if (window_list != NULL)
+ window_list->prev = NULL;
+ } else {
+ list->prev->next = list->next;
+ if (list->next != NULL) {
+ list->next->prev = list->prev;
+ }
+ }
+ break;
+ }
+}
+
static struct gui_window *
gui_window_create(struct browser_window *bw,
@@ -1514,12 +1753,17 @@ gui_window_create(struct browser_window *bw,
/* map and request redraw of gui window */
fbtk_set_mapping(gw->window, true);
+ /* Add it to the window list */
+ gui_window_add_to_window_list(gw);
+
return gw;
}
static void
gui_window_destroy(struct gui_window *gw)
{
+ gui_window_remove_from_window_list(gw);
+
fbtk_destroy_widget(gw->window);
free(gw);
@@ -1903,6 +2147,34 @@ main(int argc, char** argv)
return 0;
}
+void gui_resize(fbtk_widget_t *root, int width, int height)
+{
+ struct gui_window *gw;
+ nsfb_t *nsfb = fbtk_get_nsfb(root);
+
+ /* Enforce a minimum */
+ if (width < 300)
+ width = 300;
+ if (height < 200)
+ height = 200;
+
+ if (framebuffer_resize(nsfb, width, height, febpp) == false) {
+ return;
+ }
+
+ fbtk_set_pos_and_size(root, 0, 0, width, height);
+
+ fewidth = width;
+ feheight = height;
+
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ resize_normal_browser_window(gw,
+ nsoption_int(fb_furniture_size));
+ }
+
+ fbtk_request_redraw(root);
+}
+
/*
* Local Variables:
diff --git a/framebuffer/gui.h b/framebuffer/gui.h
index c1fa3cc1d..e102b2551 100644
--- a/framebuffer/gui.h
+++ b/framebuffer/gui.h
@@ -20,6 +20,7 @@
#define NETSURF_FB_GUI_H
typedef struct fb_cursor_s fb_cursor_t;
+typedef struct fbtk_widget_s fbtk_widget_t;
/* bounding box */
typedef struct nsfb_bbox_s bbox_t;
@@ -41,16 +42,25 @@ struct gui_window {
struct fbtk_widget_s *window;
struct fbtk_widget_s *back;
struct fbtk_widget_s *forward;
+ struct fbtk_widget_s *history;
+ struct fbtk_widget_s *stop;
+ struct fbtk_widget_s *reload;
+ struct fbtk_widget_s *close;
struct fbtk_widget_s *url;
struct fbtk_widget_s *status;
struct fbtk_widget_s *throbber;
struct fbtk_widget_s *hscroll;
struct fbtk_widget_s *vscroll;
struct fbtk_widget_s *browser;
+ struct fbtk_widget_s *toolbar;
+ struct fbtk_widget_s *bottom_right;
int throbber_index;
struct gui_localhistory *localhistory;
+
+ struct gui_window *next;
+ struct gui_window *prev;
};
@@ -59,6 +69,8 @@ extern struct gui_window *window_list;
struct gui_localhistory *fb_create_localhistory(struct browser_window *bw, struct fbtk_widget_s *parent, int furniture_width);
void fb_localhistory_map(struct gui_localhistory * glh);
+void gui_resize(fbtk_widget_t *root, int width, int height);
+
#endif /* NETSURF_FB_GUI_H */