netsurf: branch master updated. ad53da023d7126286d2b8944d52ecf65ff801a24
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/ad53da023d7126286d2b8...
...commit http://git.netsurf-browser.org/netsurf.git/commit/ad53da023d7126286d2b894...
...tree http://git.netsurf-browser.org/netsurf.git/tree/ad53da023d7126286d2b8944d...
The branch, master has been updated
via ad53da023d7126286d2b8944d52ecf65ff801a24 (commit)
via 948f2dbed66acdd11f810408b3f214dbf8972c36 (commit)
from d0966c9d3f372b1e70e6231b9b41c04b464410f7 (commit)
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=ad53da023d7126286d2...
commit ad53da023d7126286d2b8944d52ecf65ff801a24
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Optimise redraw of single line textarea. When single line textarea is unscrolled, only the changed area is redrawn after edits.
diff --git a/desktop/textarea.c b/desktop/textarea.c
index a96b061..8bf0cf0 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -747,12 +747,17 @@ static void textarea_scrollbar_callback(void *client_data,
/**
* Reflow a single line textarea
*
- * \param ta Text area to reflow
+ * \param ta Textarea widget to reflow
+ * \param b_off 0-based byte offset in ta->show's text to start of modification
+ * \param r Modified/reduced to area where redraw is required
* \return true on success false otherwise
*/
-static bool textarea_reflow_singleline(struct textarea *ta)
+static bool textarea_reflow_singleline(struct textarea *ta, size_t b_off,
+ struct rect *r)
{
int x;
+ int shift;
+ int retained_width = 0;
int w = ta->vis_width - 2 * ta->border_width -
ta->pad_left - ta->pad_right;
@@ -766,6 +771,10 @@ static bool textarea_reflow_singleline(struct textarea *ta)
return false;
}
ta->lines_alloc_size = LINE_CHUNK_SIZE;
+
+ ta->lines[0].b_start = 0;
+ ta->lines[0].b_length = 0;
+ ta->lines[0].width = 0;
}
if (ta->flags & TEXTAREA_PASSWORD &&
@@ -802,12 +811,23 @@ static bool textarea_reflow_singleline(struct textarea *ta)
ta->password.utf8_len = ta->text.utf8_len;
}
- ta->lines[0].b_start = 0;
- ta->lines[0].b_length = ta->show->len - 1;
-
nsfont.font_width(&ta->fstyle, ta->show->data,
ta->show->len - 1, &x);
+ if (b_off != ta->lines[0].b_length) {
+ nsfont.font_width(&ta->fstyle, ta->show->data,
+ b_off, &retained_width);
+ } else {
+ retained_width = ta->lines[0].width;
+ }
+
+ shift = ta->border_width + ta->pad_left - ta->scroll_x;
+
+ r->x0 = max(r->x0, retained_width + shift - 1);
+ r->x1 = min(r->x1, max(x, ta->lines[0].width) + shift + 1);
+
+ ta->lines[0].b_start = 0;
+ ta->lines[0].b_length = ta->show->len - 1;
ta->lines[0].width = x;
if (x > w)
@@ -1158,6 +1178,7 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
size_t b_off, size_t b_len, int *byte_delta, struct rect *r)
{
int char_delta, line;
+ const size_t show_b_off = b_off;
if (ta->flags & TEXTAREA_READONLY)
return true;
@@ -1218,7 +1239,7 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
if (!textarea_reflow_multiline(ta, line))
return false;
} else {
- if (!textarea_reflow_singleline(ta))
+ if (!textarea_reflow_singleline(ta, show_b_off, r))
return false;
}
@@ -1274,6 +1295,7 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
bool add_to_clipboard, int *byte_delta, struct rect *r)
{
int char_delta, line;
+ const size_t show_b_off = b_start;
*byte_delta = 0;
if ((ta->flags & TEXTAREA_READONLY) &&
@@ -1372,7 +1394,7 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
if (!textarea_reflow_multiline(ta, line))
return false;
} else {
- if (!textarea_reflow_singleline(ta))
+ if (!textarea_reflow_singleline(ta, show_b_off, r))
return false;
}
@@ -1476,6 +1498,7 @@ struct textarea *textarea_create(const textarea_flags flags,
textarea_client_callback callback, void *data)
{
struct textarea *ret;
+ struct rect r = {0, 0, 0, 0};
/* Sanity check flags */
assert(!(flags & TEXTAREA_MULTILINE &&
@@ -1575,7 +1598,7 @@ struct textarea *textarea_create(const textarea_flags flags,
if (flags & TEXTAREA_MULTILINE)
textarea_reflow_multiline(ret, 0);
else
- textarea_reflow_singleline(ret);
+ textarea_reflow_singleline(ret, 0, &r);
return ret;
}
@@ -1602,6 +1625,7 @@ void textarea_destroy(struct textarea *ta)
bool textarea_set_text(struct textarea *ta, const char *text)
{
unsigned int len = strlen(text) + 1;
+ struct rect r = {0, 0, 0, 0};
if (len >= ta->text.alloc) {
char *temp = realloc(ta->text.data, len + TA_ALLOC_STEP);
@@ -1623,7 +1647,7 @@ bool textarea_set_text(struct textarea *ta, const char *text)
if (!textarea_reflow_multiline(ta, 0))
return false;
} else {
- if (!textarea_reflow_singleline(ta))
+ if (!textarea_reflow_singleline(ta, 0, &r))
return false;
}
@@ -2437,21 +2461,18 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
/* TODO: redraw only the bit that changed */
msg.ta = ta;
msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
- msg.data.redraw.x0 = ta->border_width;
- msg.data.redraw.y0 = ta->border_width;
if (bar_x != (ta->bar_x != NULL) || bar_y != (ta->bar_y != NULL) ||
h_extent != ta->h_extent || v_extent != ta->v_extent) {
/* Must redraw since scrollbars have changed */
+ msg.data.redraw.x0 = ta->border_width;
+ msg.data.redraw.y0 = ta->border_width;
msg.data.redraw.x1 = ta->vis_width - ta->border_width;
msg.data.redraw.y1 = ta->vis_height - ta->border_width;
ta->callback(ta->data, &msg);
} else if (redraw) {
- msg.data.redraw.x1 = ta->vis_width - ta->border_width -
- ((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
- msg.data.redraw.y1 = ta->vis_height - ta->border_width -
- ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
+ msg.data.redraw = r;
ta->callback(ta->data, &msg);
}
@@ -2756,6 +2777,8 @@ void textarea_get_dimensions(struct textarea *ta, int *width, int *height)
/* exported interface, documented in textarea.h */
void textarea_set_dimensions(struct textarea *ta, int width, int height)
{
+ struct rect r = {0, 0, 0, 0};
+
ta->vis_width = width;
ta->vis_height = height;
@@ -2764,7 +2787,7 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
if (ta->flags & TEXTAREA_MULTILINE) {
textarea_reflow_multiline(ta, 0);
} else {
- textarea_reflow_singleline(ta);
+ textarea_reflow_singleline(ta, 0, &r);
}
}
@@ -2773,6 +2796,8 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
void textarea_set_layout(struct textarea *ta, int width, int height,
int top, int right, int bottom, int left)
{
+ struct rect r = {0, 0, 0, 0};
+
ta->vis_width = width;
ta->vis_height = height;
ta->pad_top = top;
@@ -2785,7 +2810,7 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
if (ta->flags & TEXTAREA_MULTILINE) {
textarea_reflow_multiline(ta, 0);
} else {
- textarea_reflow_singleline(ta);
+ textarea_reflow_singleline(ta, 0, &r);
}
}
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=948f2dbed66acdd11f8...
commit 948f2dbed66acdd11f810408b3f214dbf8972c36
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Split reflow into two functions for single or multi line textareas.
diff --git a/desktop/textarea.c b/desktop/textarea.c
index d23a021..a96b061 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -745,25 +745,18 @@ static void textarea_scrollbar_callback(void *client_data,
/**
- * Reflow a text area from the given line onwards
+ * Reflow a single line textarea
*
* \param ta Text area to reflow
- * \param start Line number to begin reflow on
* \return true on success false otherwise
*/
-static bool textarea_reflow(struct textarea *ta, unsigned int start)
+static bool textarea_reflow_singleline(struct textarea *ta)
{
- char *text;
- unsigned int len;
- size_t b_off;
int x;
- char *space, *para_end;
- unsigned int line; /* line count */
- unsigned int scroll_lines;
- int avail_width;
- int h_extent; /* horizontal extent */
- int v_extent; /* vertical extent */
- bool restart = false;
+ int w = ta->vis_width - 2 * ta->border_width -
+ ta->pad_left - ta->pad_right;
+
+ assert(!(ta->flags & TEXTAREA_MULTILINE));
if (ta->lines == NULL) {
ta->lines =
@@ -775,60 +768,90 @@ static bool textarea_reflow(struct textarea *ta, unsigned int start)
ta->lines_alloc_size = LINE_CHUNK_SIZE;
}
- if (!(ta->flags & TEXTAREA_MULTILINE)) {
- /* Single line */
- int w = ta->vis_width - 2 * ta->border_width -
- ta->pad_left - ta->pad_right;
-
- if (ta->flags & TEXTAREA_PASSWORD &&
- ta->text.utf8_len != ta->password.utf8_len) {
- /* Make password-obscured text have same number of
- * characters as underlying text */
- unsigned int c, b;
- int diff = ta->text.utf8_len - ta->password.utf8_len;
- unsigned int rep_len = PASSWORD_REPLACEMENT_W;
- unsigned int b_len = ta->text.utf8_len * rep_len + 1;
-
- if (diff > 0 && b_len > ta->password.alloc) {
- /* Increase password alloaction */
- char *temp = realloc(ta->password.data,
- b_len + TA_ALLOC_STEP);
- if (temp == NULL) {
- LOG(("realloc failed"));
- return false;
- }
-
- ta->password.data = temp;
- ta->password.alloc = b_len + TA_ALLOC_STEP;
+ if (ta->flags & TEXTAREA_PASSWORD &&
+ ta->text.utf8_len != ta->password.utf8_len) {
+ /* Make password-obscured text have same number of
+ * characters as underlying text */
+ unsigned int c, b;
+ int diff = ta->text.utf8_len - ta->password.utf8_len;
+ unsigned int rep_len = PASSWORD_REPLACEMENT_W;
+ unsigned int b_len = ta->text.utf8_len * rep_len + 1;
+
+ if (diff > 0 && b_len > ta->password.alloc) {
+ /* Increase password alloaction */
+ char *temp = realloc(ta->password.data,
+ b_len + TA_ALLOC_STEP);
+ if (temp == NULL) {
+ LOG(("realloc failed"));
+ return false;
}
- b_len--;
- for (c = 0; c < b_len; c += rep_len) {
- for (b = 0; b < rep_len; b++) {
- ta->password.data[c + b] =
- PASSWORD_REPLACEMENT[b];
- }
+ ta->password.data = temp;
+ ta->password.alloc = b_len + TA_ALLOC_STEP;
+ }
+
+ b_len--;
+ for (c = 0; c < b_len; c += rep_len) {
+ for (b = 0; b < rep_len; b++) {
+ ta->password.data[c + b] =
+ PASSWORD_REPLACEMENT[b];
}
- ta->password.data[b_len] = '\0';
- ta->password.len = b_len + 1;
- ta->password.utf8_len = ta->text.utf8_len;
}
+ ta->password.data[b_len] = '\0';
+ ta->password.len = b_len + 1;
+ ta->password.utf8_len = ta->text.utf8_len;
+ }
- ta->lines[0].b_start = 0;
- ta->lines[0].b_length = ta->show->len - 1;
+ ta->lines[0].b_start = 0;
+ ta->lines[0].b_length = ta->show->len - 1;
- nsfont.font_width(&ta->fstyle, ta->show->data,
- ta->show->len - 1, &x);
+ nsfont.font_width(&ta->fstyle, ta->show->data,
+ ta->show->len - 1, &x);
- ta->lines[0].width = x;
+ ta->lines[0].width = x;
- if (x > w)
- w = x;
+ if (x > w)
+ w = x;
- ta->h_extent = w + ta->pad_left + ta->pad_right;
- ta->line_count = 1;
+ ta->h_extent = w + ta->pad_left + ta->pad_right;
+ ta->line_count = 1;
- return true;
+ return true;
+}
+
+
+
+/**
+ * Reflow a text area from the given line onwards
+ *
+ * \param ta Text area to reflow
+ * \param start Line number to begin reflow on
+ * \return true on success false otherwise
+ */
+static bool textarea_reflow_multiline(struct textarea *ta, unsigned int start)
+{
+ char *text;
+ unsigned int len;
+ size_t b_off;
+ int x;
+ char *space, *para_end;
+ unsigned int line; /* line count */
+ unsigned int scroll_lines;
+ int avail_width;
+ int h_extent; /* horizontal extent */
+ int v_extent; /* vertical extent */
+ bool restart = false;
+
+ assert(ta->flags & TEXTAREA_MULTILINE);
+
+ if (ta->lines == NULL) {
+ ta->lines =
+ malloc(LINE_CHUNK_SIZE * sizeof(struct line_info));
+ if (ta->lines == NULL) {
+ LOG(("malloc failed"));
+ return false;
+ }
+ ta->lines_alloc_size = LINE_CHUNK_SIZE;
}
/* Find max number of lines before vertical scrollbar is required */
@@ -1125,13 +1148,14 @@ static bool textarea_set_caret_xy(struct textarea *ta, int x, int y,
* \param text UTF-8 text to insert
* \param b_off 0-based byte offset in ta->show's text to insert at
* \param b_len Byte length of UTF-8 text
- * \param byte_delta Change in number of bytes in textarea (ta->show)
+ * \param byte_delta Updated to change in byte count in textarea (ta->show)
+ * \param r Modified/reduced to area where redraw is required
* \return false on memory exhaustion, true otherwise
*
* Note: b_off must be for ta->show
*/
static bool textarea_insert_text(struct textarea *ta, const char *text,
- size_t b_off, size_t b_len, int *byte_delta)
+ size_t b_off, size_t b_len, int *byte_delta, struct rect *r)
{
int char_delta, line;
@@ -1173,10 +1197,12 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
char_delta = ta->text.utf8_len;
*byte_delta = ta->text.len;
+ /* Update lengths, and normalise */
ta->text.len += b_len;
ta->text.utf8_len += utf8_bounded_length(text, b_len);
textarea_normalise_text(ta, b_off, b_len);
+ /* Get byte delta */
if (ta->flags & TEXTAREA_PASSWORD) {
char_delta = ta->text.utf8_len - char_delta;
*byte_delta = char_delta * PASSWORD_REPLACEMENT_W;
@@ -1184,11 +1210,19 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
*byte_delta = ta->text.len - *byte_delta;
}
- for (line = 0; line < ta->line_count - 1; line++)
- if (ta->lines[line + 1].b_start > b_off)
- break;
+ /* See to reflow */
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ for (line = 0; line < ta->line_count - 1; line++)
+ if (ta->lines[line + 1].b_start > b_off)
+ break;
+ if (!textarea_reflow_multiline(ta, line))
+ return false;
+ } else {
+ if (!textarea_reflow_singleline(ta))
+ return false;
+ }
- return textarea_reflow(ta, line);
+ return true;
}
@@ -1228,7 +1262,8 @@ static inline void textarea_char_to_byte_offset(struct textarea_utf8 *text,
* \param rep Replacement UTF-8 text to insert
* \param rep_len Byte length of replacement UTF-8 text
* \param add_to_clipboard True iff replaced text to be added to clipboard
- * \param byte_delta Change in number of bytes in textarea (ta->show)
+ * \param byte_delta Updated to change in byte count in textarea (ta->show)
+ * \param r Updated to area where redraw is required
* \return false on memory exhaustion, true otherwise
*
* Note, b_start and b_end must be the byte offsets in ta->show, so in the
@@ -1236,7 +1271,7 @@ static inline void textarea_char_to_byte_offset(struct textarea_utf8 *text,
*/
static bool textarea_replace_text(struct textarea *ta, size_t b_start,
size_t b_end, const char *rep, size_t rep_len,
- bool add_to_clipboard, int *byte_delta)
+ bool add_to_clipboard, int *byte_delta, struct rect *r)
{
int char_delta, line;
*byte_delta = 0;
@@ -1251,9 +1286,18 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
if (b_end > ta->show->len - 1)
b_end = ta->show->len - 1;
+ /* Set up initial redraw rect */
+ r->x0 = ta->border_width;
+ r->y0 = ta->border_width;
+ r->x1 = ta->vis_width - ta->border_width -
+ ((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
+ r->y1 = ta->vis_height - ta->border_width -
+ ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
+
+ /* Early exit if just inserting */
if (b_start == b_end && rep != NULL)
return textarea_insert_text(ta, rep, b_start, rep_len,
- byte_delta);
+ byte_delta, r);
if (b_start > b_end)
return false;
@@ -1307,10 +1351,12 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
char_delta = ta->text.utf8_len;
*byte_delta = ta->text.len;
+ /* Update lengths, and normalise */
ta->text.len += (int)rep_len - (b_end - b_start);
ta->text.utf8_len = utf8_length(ta->text.data);
textarea_normalise_text(ta, b_start, rep_len);
+ /* Get byte delta */
if (ta->flags & TEXTAREA_PASSWORD) {
char_delta = ta->text.utf8_len - char_delta;
*byte_delta = char_delta * PASSWORD_REPLACEMENT_W;
@@ -1318,11 +1364,19 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
*byte_delta = ta->text.len - *byte_delta;
}
- for (line = 0; line < ta->line_count - 1; line++)
- if (ta->lines[line + 1].b_start > b_start)
- break;
+ /* See to reflow */
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ for (line = 0; line < ta->line_count - 1; line++)
+ if (ta->lines[line + 1].b_start > b_start)
+ break;
+ if (!textarea_reflow_multiline(ta, line))
+ return false;
+ } else {
+ if (!textarea_reflow_singleline(ta))
+ return false;
+ }
- return textarea_reflow(ta, line);
+ return true;
}
@@ -1517,7 +1571,11 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->lines_alloc_size = 0;
textarea_setup_text_offsets(ret);
- textarea_reflow(ret, 0);
+
+ if (flags & TEXTAREA_MULTILINE)
+ textarea_reflow_multiline(ret, 0);
+ else
+ textarea_reflow_singleline(ret);
return ret;
}
@@ -1561,7 +1619,15 @@ bool textarea_set_text(struct textarea *ta, const char *text)
textarea_normalise_text(ta, 0, len);
- return textarea_reflow(ta, 0);
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ if (!textarea_reflow_multiline(ta, 0))
+ return false;
+ } else {
+ if (!textarea_reflow_singleline(ta))
+ return false;
+ }
+
+ return true;
}
@@ -1570,6 +1636,7 @@ bool textarea_drop_text(struct textarea *ta, const char *text,
size_t text_length)
{
struct textarea_msg msg;
+ struct rect r; /**< Redraw rectangle */
unsigned int caret_pos;
int byte_delta;
@@ -1583,14 +1650,14 @@ bool textarea_drop_text(struct textarea *ta, const char *text,
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta, ta->sel_start, ta->sel_end,
- text, text_length, false, &byte_delta))
+ text, text_length, false, &byte_delta, &r))
return false;
caret_pos = ta->sel_end;
ta->sel_start = ta->sel_end = -1;
} else {
if (!textarea_replace_text(ta, caret_pos, caret_pos,
- text, text_length, false, &byte_delta))
+ text, text_length, false, &byte_delta, &r))
return false;
}
@@ -1961,6 +2028,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
bool textarea_keypress(struct textarea *ta, uint32_t key)
{
struct textarea_msg msg;
+ struct rect r; /**< Redraw rectangle */
char utf8[6];
unsigned int caret, length, b_off, b_len;
int h_extent = ta->h_extent;
@@ -1988,14 +2056,14 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end, utf8,
- length, false, &byte_delta))
+ length, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
} else {
if (!textarea_replace_text(ta, caret, caret,
- utf8, length, false, &byte_delta))
+ utf8, length, false, &byte_delta, &r))
return false;
redraw = true;
}
@@ -2009,7 +2077,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- NULL, 0, true, &byte_delta))
+ NULL, 0, true, &byte_delta, &r))
return false;
}
break;
@@ -2019,7 +2087,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2027,7 +2095,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
} else if (caret > 0) {
b_off = utf8_prev(ta->show->data, caret);
if (!textarea_replace_text(ta, b_off, caret,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
redraw = true;
}
@@ -2039,7 +2107,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2048,7 +2116,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
b_off = utf8_next(ta->show->data,
ta->show->len - 1, caret);
if (!textarea_replace_text(ta, caret, b_off,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = b_off;
redraw = true;
@@ -2063,14 +2131,16 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "\n", 1, false, &byte_delta))
+ "\n", 1, false,
+ &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
} else {
if (!textarea_replace_text(ta, caret, caret,
- "\n", 1, false, &byte_delta))
+ "\n", 1, false,
+ &byte_delta, &r))
return false;
redraw = true;
}
@@ -2092,7 +2162,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
clipboard, clipboard_length,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2101,7 +2171,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (!textarea_replace_text(ta,
caret, caret,
clipboard, clipboard_length,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
redraw = true;
}
@@ -2116,7 +2186,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, true, &byte_delta))
+ "", 0, true, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2291,7 +2361,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
@@ -2302,14 +2372,14 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
b_len = ta->lines[line].b_length;
if (!textarea_replace_text(ta, caret,
caret + b_len, "", 0,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
caret = caret + b_len;
} else if (caret < ta->show->len - 1) {
/* Delete blank line */
if (!textarea_replace_text(ta,
caret, caret + 1, "", 0,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
caret++;
}
@@ -2323,7 +2393,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
@@ -2331,7 +2401,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
b_len = ta->lines[line].b_length;
b_off = ta->lines[line].b_start + b_len;
if (!textarea_replace_text(ta, caret, b_off,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = b_off;
redraw = true;
@@ -2344,7 +2414,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
@@ -2352,7 +2422,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (!textarea_replace_text(ta,
caret - ta->caret_pos.byte_off,
caret, "", 0, false,
- &byte_delta))
+ &byte_delta, &r))
return false;
redraw = true;
}
@@ -2690,7 +2760,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
ta->vis_height = height;
textarea_setup_text_offsets(ta);
- textarea_reflow(ta, 0);
+
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ textarea_reflow_multiline(ta, 0);
+ } else {
+ textarea_reflow_singleline(ta);
+ }
}
@@ -2706,7 +2781,12 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_left = left;
textarea_setup_text_offsets(ta);
- textarea_reflow(ta, 0);
+
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ textarea_reflow_multiline(ta, 0);
+ } else {
+ textarea_reflow_singleline(ta);
+ }
}
-----------------------------------------------------------------------
Summary of changes:
desktop/textarea.c | 307 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 206 insertions(+), 101 deletions(-)
diff --git a/desktop/textarea.c b/desktop/textarea.c
index d23a021..8bf0cf0 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -745,25 +745,23 @@ static void textarea_scrollbar_callback(void *client_data,
/**
- * Reflow a text area from the given line onwards
+ * Reflow a single line textarea
*
- * \param ta Text area to reflow
- * \param start Line number to begin reflow on
+ * \param ta Textarea widget to reflow
+ * \param b_off 0-based byte offset in ta->show's text to start of modification
+ * \param r Modified/reduced to area where redraw is required
* \return true on success false otherwise
*/
-static bool textarea_reflow(struct textarea *ta, unsigned int start)
+static bool textarea_reflow_singleline(struct textarea *ta, size_t b_off,
+ struct rect *r)
{
- char *text;
- unsigned int len;
- size_t b_off;
int x;
- char *space, *para_end;
- unsigned int line; /* line count */
- unsigned int scroll_lines;
- int avail_width;
- int h_extent; /* horizontal extent */
- int v_extent; /* vertical extent */
- bool restart = false;
+ int shift;
+ int retained_width = 0;
+ int w = ta->vis_width - 2 * ta->border_width -
+ ta->pad_left - ta->pad_right;
+
+ assert(!(ta->flags & TEXTAREA_MULTILINE));
if (ta->lines == NULL) {
ta->lines =
@@ -773,62 +771,107 @@ static bool textarea_reflow(struct textarea *ta, unsigned int start)
return false;
}
ta->lines_alloc_size = LINE_CHUNK_SIZE;
- }
-
- if (!(ta->flags & TEXTAREA_MULTILINE)) {
- /* Single line */
- int w = ta->vis_width - 2 * ta->border_width -
- ta->pad_left - ta->pad_right;
- if (ta->flags & TEXTAREA_PASSWORD &&
- ta->text.utf8_len != ta->password.utf8_len) {
- /* Make password-obscured text have same number of
- * characters as underlying text */
- unsigned int c, b;
- int diff = ta->text.utf8_len - ta->password.utf8_len;
- unsigned int rep_len = PASSWORD_REPLACEMENT_W;
- unsigned int b_len = ta->text.utf8_len * rep_len + 1;
-
- if (diff > 0 && b_len > ta->password.alloc) {
- /* Increase password alloaction */
- char *temp = realloc(ta->password.data,
- b_len + TA_ALLOC_STEP);
- if (temp == NULL) {
- LOG(("realloc failed"));
- return false;
- }
+ ta->lines[0].b_start = 0;
+ ta->lines[0].b_length = 0;
+ ta->lines[0].width = 0;
+ }
- ta->password.data = temp;
- ta->password.alloc = b_len + TA_ALLOC_STEP;
+ if (ta->flags & TEXTAREA_PASSWORD &&
+ ta->text.utf8_len != ta->password.utf8_len) {
+ /* Make password-obscured text have same number of
+ * characters as underlying text */
+ unsigned int c, b;
+ int diff = ta->text.utf8_len - ta->password.utf8_len;
+ unsigned int rep_len = PASSWORD_REPLACEMENT_W;
+ unsigned int b_len = ta->text.utf8_len * rep_len + 1;
+
+ if (diff > 0 && b_len > ta->password.alloc) {
+ /* Increase password alloaction */
+ char *temp = realloc(ta->password.data,
+ b_len + TA_ALLOC_STEP);
+ if (temp == NULL) {
+ LOG(("realloc failed"));
+ return false;
}
- b_len--;
- for (c = 0; c < b_len; c += rep_len) {
- for (b = 0; b < rep_len; b++) {
- ta->password.data[c + b] =
- PASSWORD_REPLACEMENT[b];
- }
+ ta->password.data = temp;
+ ta->password.alloc = b_len + TA_ALLOC_STEP;
+ }
+
+ b_len--;
+ for (c = 0; c < b_len; c += rep_len) {
+ for (b = 0; b < rep_len; b++) {
+ ta->password.data[c + b] =
+ PASSWORD_REPLACEMENT[b];
}
- ta->password.data[b_len] = '\0';
- ta->password.len = b_len + 1;
- ta->password.utf8_len = ta->text.utf8_len;
}
+ ta->password.data[b_len] = '\0';
+ ta->password.len = b_len + 1;
+ ta->password.utf8_len = ta->text.utf8_len;
+ }
- ta->lines[0].b_start = 0;
- ta->lines[0].b_length = ta->show->len - 1;
+ nsfont.font_width(&ta->fstyle, ta->show->data,
+ ta->show->len - 1, &x);
+ if (b_off != ta->lines[0].b_length) {
nsfont.font_width(&ta->fstyle, ta->show->data,
- ta->show->len - 1, &x);
+ b_off, &retained_width);
+ } else {
+ retained_width = ta->lines[0].width;
+ }
- ta->lines[0].width = x;
+ shift = ta->border_width + ta->pad_left - ta->scroll_x;
- if (x > w)
- w = x;
+ r->x0 = max(r->x0, retained_width + shift - 1);
+ r->x1 = min(r->x1, max(x, ta->lines[0].width) + shift + 1);
- ta->h_extent = w + ta->pad_left + ta->pad_right;
- ta->line_count = 1;
+ ta->lines[0].b_start = 0;
+ ta->lines[0].b_length = ta->show->len - 1;
+ ta->lines[0].width = x;
- return true;
+ if (x > w)
+ w = x;
+
+ ta->h_extent = w + ta->pad_left + ta->pad_right;
+ ta->line_count = 1;
+
+ return true;
+}
+
+
+
+/**
+ * Reflow a text area from the given line onwards
+ *
+ * \param ta Text area to reflow
+ * \param start Line number to begin reflow on
+ * \return true on success false otherwise
+ */
+static bool textarea_reflow_multiline(struct textarea *ta, unsigned int start)
+{
+ char *text;
+ unsigned int len;
+ size_t b_off;
+ int x;
+ char *space, *para_end;
+ unsigned int line; /* line count */
+ unsigned int scroll_lines;
+ int avail_width;
+ int h_extent; /* horizontal extent */
+ int v_extent; /* vertical extent */
+ bool restart = false;
+
+ assert(ta->flags & TEXTAREA_MULTILINE);
+
+ if (ta->lines == NULL) {
+ ta->lines =
+ malloc(LINE_CHUNK_SIZE * sizeof(struct line_info));
+ if (ta->lines == NULL) {
+ LOG(("malloc failed"));
+ return false;
+ }
+ ta->lines_alloc_size = LINE_CHUNK_SIZE;
}
/* Find max number of lines before vertical scrollbar is required */
@@ -1125,15 +1168,17 @@ static bool textarea_set_caret_xy(struct textarea *ta, int x, int y,
* \param text UTF-8 text to insert
* \param b_off 0-based byte offset in ta->show's text to insert at
* \param b_len Byte length of UTF-8 text
- * \param byte_delta Change in number of bytes in textarea (ta->show)
+ * \param byte_delta Updated to change in byte count in textarea (ta->show)
+ * \param r Modified/reduced to area where redraw is required
* \return false on memory exhaustion, true otherwise
*
* Note: b_off must be for ta->show
*/
static bool textarea_insert_text(struct textarea *ta, const char *text,
- size_t b_off, size_t b_len, int *byte_delta)
+ size_t b_off, size_t b_len, int *byte_delta, struct rect *r)
{
int char_delta, line;
+ const size_t show_b_off = b_off;
if (ta->flags & TEXTAREA_READONLY)
return true;
@@ -1173,10 +1218,12 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
char_delta = ta->text.utf8_len;
*byte_delta = ta->text.len;
+ /* Update lengths, and normalise */
ta->text.len += b_len;
ta->text.utf8_len += utf8_bounded_length(text, b_len);
textarea_normalise_text(ta, b_off, b_len);
+ /* Get byte delta */
if (ta->flags & TEXTAREA_PASSWORD) {
char_delta = ta->text.utf8_len - char_delta;
*byte_delta = char_delta * PASSWORD_REPLACEMENT_W;
@@ -1184,11 +1231,19 @@ static bool textarea_insert_text(struct textarea *ta, const char *text,
*byte_delta = ta->text.len - *byte_delta;
}
- for (line = 0; line < ta->line_count - 1; line++)
- if (ta->lines[line + 1].b_start > b_off)
- break;
+ /* See to reflow */
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ for (line = 0; line < ta->line_count - 1; line++)
+ if (ta->lines[line + 1].b_start > b_off)
+ break;
+ if (!textarea_reflow_multiline(ta, line))
+ return false;
+ } else {
+ if (!textarea_reflow_singleline(ta, show_b_off, r))
+ return false;
+ }
- return textarea_reflow(ta, line);
+ return true;
}
@@ -1228,7 +1283,8 @@ static inline void textarea_char_to_byte_offset(struct textarea_utf8 *text,
* \param rep Replacement UTF-8 text to insert
* \param rep_len Byte length of replacement UTF-8 text
* \param add_to_clipboard True iff replaced text to be added to clipboard
- * \param byte_delta Change in number of bytes in textarea (ta->show)
+ * \param byte_delta Updated to change in byte count in textarea (ta->show)
+ * \param r Updated to area where redraw is required
* \return false on memory exhaustion, true otherwise
*
* Note, b_start and b_end must be the byte offsets in ta->show, so in the
@@ -1236,9 +1292,10 @@ static inline void textarea_char_to_byte_offset(struct textarea_utf8 *text,
*/
static bool textarea_replace_text(struct textarea *ta, size_t b_start,
size_t b_end, const char *rep, size_t rep_len,
- bool add_to_clipboard, int *byte_delta)
+ bool add_to_clipboard, int *byte_delta, struct rect *r)
{
int char_delta, line;
+ const size_t show_b_off = b_start;
*byte_delta = 0;
if ((ta->flags & TEXTAREA_READONLY) &&
@@ -1251,9 +1308,18 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
if (b_end > ta->show->len - 1)
b_end = ta->show->len - 1;
+ /* Set up initial redraw rect */
+ r->x0 = ta->border_width;
+ r->y0 = ta->border_width;
+ r->x1 = ta->vis_width - ta->border_width -
+ ((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
+ r->y1 = ta->vis_height - ta->border_width -
+ ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
+
+ /* Early exit if just inserting */
if (b_start == b_end && rep != NULL)
return textarea_insert_text(ta, rep, b_start, rep_len,
- byte_delta);
+ byte_delta, r);
if (b_start > b_end)
return false;
@@ -1307,10 +1373,12 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
char_delta = ta->text.utf8_len;
*byte_delta = ta->text.len;
+ /* Update lengths, and normalise */
ta->text.len += (int)rep_len - (b_end - b_start);
ta->text.utf8_len = utf8_length(ta->text.data);
textarea_normalise_text(ta, b_start, rep_len);
+ /* Get byte delta */
if (ta->flags & TEXTAREA_PASSWORD) {
char_delta = ta->text.utf8_len - char_delta;
*byte_delta = char_delta * PASSWORD_REPLACEMENT_W;
@@ -1318,11 +1386,19 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start,
*byte_delta = ta->text.len - *byte_delta;
}
- for (line = 0; line < ta->line_count - 1; line++)
- if (ta->lines[line + 1].b_start > b_start)
- break;
+ /* See to reflow */
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ for (line = 0; line < ta->line_count - 1; line++)
+ if (ta->lines[line + 1].b_start > b_start)
+ break;
+ if (!textarea_reflow_multiline(ta, line))
+ return false;
+ } else {
+ if (!textarea_reflow_singleline(ta, show_b_off, r))
+ return false;
+ }
- return textarea_reflow(ta, line);
+ return true;
}
@@ -1422,6 +1498,7 @@ struct textarea *textarea_create(const textarea_flags flags,
textarea_client_callback callback, void *data)
{
struct textarea *ret;
+ struct rect r = {0, 0, 0, 0};
/* Sanity check flags */
assert(!(flags & TEXTAREA_MULTILINE &&
@@ -1517,7 +1594,11 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->lines_alloc_size = 0;
textarea_setup_text_offsets(ret);
- textarea_reflow(ret, 0);
+
+ if (flags & TEXTAREA_MULTILINE)
+ textarea_reflow_multiline(ret, 0);
+ else
+ textarea_reflow_singleline(ret, 0, &r);
return ret;
}
@@ -1544,6 +1625,7 @@ void textarea_destroy(struct textarea *ta)
bool textarea_set_text(struct textarea *ta, const char *text)
{
unsigned int len = strlen(text) + 1;
+ struct rect r = {0, 0, 0, 0};
if (len >= ta->text.alloc) {
char *temp = realloc(ta->text.data, len + TA_ALLOC_STEP);
@@ -1561,7 +1643,15 @@ bool textarea_set_text(struct textarea *ta, const char *text)
textarea_normalise_text(ta, 0, len);
- return textarea_reflow(ta, 0);
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ if (!textarea_reflow_multiline(ta, 0))
+ return false;
+ } else {
+ if (!textarea_reflow_singleline(ta, 0, &r))
+ return false;
+ }
+
+ return true;
}
@@ -1570,6 +1660,7 @@ bool textarea_drop_text(struct textarea *ta, const char *text,
size_t text_length)
{
struct textarea_msg msg;
+ struct rect r; /**< Redraw rectangle */
unsigned int caret_pos;
int byte_delta;
@@ -1583,14 +1674,14 @@ bool textarea_drop_text(struct textarea *ta, const char *text,
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta, ta->sel_start, ta->sel_end,
- text, text_length, false, &byte_delta))
+ text, text_length, false, &byte_delta, &r))
return false;
caret_pos = ta->sel_end;
ta->sel_start = ta->sel_end = -1;
} else {
if (!textarea_replace_text(ta, caret_pos, caret_pos,
- text, text_length, false, &byte_delta))
+ text, text_length, false, &byte_delta, &r))
return false;
}
@@ -1961,6 +2052,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
bool textarea_keypress(struct textarea *ta, uint32_t key)
{
struct textarea_msg msg;
+ struct rect r; /**< Redraw rectangle */
char utf8[6];
unsigned int caret, length, b_off, b_len;
int h_extent = ta->h_extent;
@@ -1988,14 +2080,14 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end, utf8,
- length, false, &byte_delta))
+ length, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
} else {
if (!textarea_replace_text(ta, caret, caret,
- utf8, length, false, &byte_delta))
+ utf8, length, false, &byte_delta, &r))
return false;
redraw = true;
}
@@ -2009,7 +2101,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- NULL, 0, true, &byte_delta))
+ NULL, 0, true, &byte_delta, &r))
return false;
}
break;
@@ -2019,7 +2111,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2027,7 +2119,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
} else if (caret > 0) {
b_off = utf8_prev(ta->show->data, caret);
if (!textarea_replace_text(ta, b_off, caret,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
redraw = true;
}
@@ -2039,7 +2131,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2048,7 +2140,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
b_off = utf8_next(ta->show->data,
ta->show->len - 1, caret);
if (!textarea_replace_text(ta, caret, b_off,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = b_off;
redraw = true;
@@ -2063,14 +2155,16 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "\n", 1, false, &byte_delta))
+ "\n", 1, false,
+ &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
} else {
if (!textarea_replace_text(ta, caret, caret,
- "\n", 1, false, &byte_delta))
+ "\n", 1, false,
+ &byte_delta, &r))
return false;
redraw = true;
}
@@ -2092,7 +2186,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
clipboard, clipboard_length,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2101,7 +2195,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (!textarea_replace_text(ta,
caret, caret,
clipboard, clipboard_length,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
redraw = true;
}
@@ -2116,7 +2210,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, true, &byte_delta))
+ "", 0, true, &byte_delta, &r))
return false;
caret = ta->sel_end;
@@ -2291,7 +2385,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
@@ -2302,14 +2396,14 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
b_len = ta->lines[line].b_length;
if (!textarea_replace_text(ta, caret,
caret + b_len, "", 0,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
caret = caret + b_len;
} else if (caret < ta->show->len - 1) {
/* Delete blank line */
if (!textarea_replace_text(ta,
caret, caret + 1, "", 0,
- false, &byte_delta))
+ false, &byte_delta, &r))
return false;
caret++;
}
@@ -2323,7 +2417,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
@@ -2331,7 +2425,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
b_len = ta->lines[line].b_length;
b_off = ta->lines[line].b_start + b_len;
if (!textarea_replace_text(ta, caret, b_off,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = b_off;
redraw = true;
@@ -2344,7 +2438,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (ta->sel_start != -1) {
if (!textarea_replace_text(ta,
ta->sel_start, ta->sel_end,
- "", 0, false, &byte_delta))
+ "", 0, false, &byte_delta, &r))
return false;
caret = ta->sel_end;
textarea_clear_selection(ta);
@@ -2352,7 +2446,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
if (!textarea_replace_text(ta,
caret - ta->caret_pos.byte_off,
caret, "", 0, false,
- &byte_delta))
+ &byte_delta, &r))
return false;
redraw = true;
}
@@ -2367,21 +2461,18 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
/* TODO: redraw only the bit that changed */
msg.ta = ta;
msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
- msg.data.redraw.x0 = ta->border_width;
- msg.data.redraw.y0 = ta->border_width;
if (bar_x != (ta->bar_x != NULL) || bar_y != (ta->bar_y != NULL) ||
h_extent != ta->h_extent || v_extent != ta->v_extent) {
/* Must redraw since scrollbars have changed */
+ msg.data.redraw.x0 = ta->border_width;
+ msg.data.redraw.y0 = ta->border_width;
msg.data.redraw.x1 = ta->vis_width - ta->border_width;
msg.data.redraw.y1 = ta->vis_height - ta->border_width;
ta->callback(ta->data, &msg);
} else if (redraw) {
- msg.data.redraw.x1 = ta->vis_width - ta->border_width -
- ((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
- msg.data.redraw.y1 = ta->vis_height - ta->border_width -
- ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
+ msg.data.redraw = r;
ta->callback(ta->data, &msg);
}
@@ -2686,11 +2777,18 @@ void textarea_get_dimensions(struct textarea *ta, int *width, int *height)
/* exported interface, documented in textarea.h */
void textarea_set_dimensions(struct textarea *ta, int width, int height)
{
+ struct rect r = {0, 0, 0, 0};
+
ta->vis_width = width;
ta->vis_height = height;
textarea_setup_text_offsets(ta);
- textarea_reflow(ta, 0);
+
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ textarea_reflow_multiline(ta, 0);
+ } else {
+ textarea_reflow_singleline(ta, 0, &r);
+ }
}
@@ -2698,6 +2796,8 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
void textarea_set_layout(struct textarea *ta, int width, int height,
int top, int right, int bottom, int left)
{
+ struct rect r = {0, 0, 0, 0};
+
ta->vis_width = width;
ta->vis_height = height;
ta->pad_top = top;
@@ -2706,7 +2806,12 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_left = left;
textarea_setup_text_offsets(ta);
- textarea_reflow(ta, 0);
+
+ if (ta->flags & TEXTAREA_MULTILINE) {
+ textarea_reflow_multiline(ta, 0);
+ } else {
+ textarea_reflow_singleline(ta, 0, &r);
+ }
}
--
NetSurf Browser
9 years, 10 months
libnsfb: branch vince/wayland created. f75a698b15f978c854cc424ee79a38e157165091
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/libnsfb.git/shortlog/f75a698b15f978c854cc4...
...commit http://git.netsurf-browser.org/libnsfb.git/commit/f75a698b15f978c854cc424...
...tree http://git.netsurf-browser.org/libnsfb.git/tree/f75a698b15f978c854cc424ee...
The branch, vince/wayland has been created
at f75a698b15f978c854cc424ee79a38e157165091 (commit)
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/libnsfb.git/commit/?id=f75a698b15f978c854c...
commit f75a698b15f978c854cc424ee79a38e157165091
Author: Vincent Sanders <vincent.sanders(a)collabora.co.uk>
Commit: Vincent Sanders <vincent.sanders(a)collabora.co.uk>
initial wayland surface connection
diff --git a/Makefile b/Makefile
index 2b07e87..89d7b6b 100644
--- a/Makefile
+++ b/Makefile
@@ -18,15 +18,21 @@ WARNFLAGS := -Wall -Wextra -Wundef -Wpointer-arith -Wcast-align \
-Wmissing-declarations -Wnested-externs -Werror -pedantic \
-Wno-overlength-strings # For nsglobe.c
CFLAGS := -g -std=c99 -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112L \
- -I$(CURDIR)/include/ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS)
+ -I$(CURDIR)/include/ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) -Wno-error
NSFB_XCB_PKG_NAMES := xcb xcb-icccm xcb-image xcb-keysyms xcb-atom
+# determine which surface handlers can be compiled based upon avalable library
$(eval $(call pkg_config_package_available,NSFB_VNC_AVAILABLE,libvncserver))
$(eval $(call pkg_config_package_available,NSFB_SDL_AVAILABLE,sdl))
$(eval $(call pkg_config_package_available,NSFB_XCB_AVAILABLE,$(NSFB_XCB_PKG_NAMES)))
$(eval $(call pkg_config_package_available,NSFB_WLD_AVAILABLE,wayland-client))
+# surfaces not detectable via pkg-config
+NSFB_ABLE_AVAILABLE := no
+NSFB_LINUX_AVAILABLE := yes
+
+# Flags and setup for each support library
ifeq ($(NSFB_SDL_AVAILABLE),yes)
$(eval $(call pkg_config_package_add_flags,sdl,CFLAGS))
$(eval $(call pkg_config_package_add_flags,sdl,TESTCFLAGS,TESTLDFLAGS))
diff --git a/src/surface/Makefile b/src/surface/Makefile
index 332d81d..ad23cc4 100644
--- a/src/surface/Makefile
+++ b/src/surface/Makefile
@@ -1,20 +1,16 @@
# Sources
-DIR_SOURCES := surface.c able.c ram.c linux.c
-ifeq ($(NSFB_SDL_AVAILABLE),yes)
- DIR_SOURCES := $(DIR_SOURCES) sdl.c
-endif
+# Common surface code and heap based surface handler
+SURFACE_HANDLER_yes := surface.c ram.c
-ifeq ($(NSFB_XCB_AVAILABLE),yes)
- DIR_SOURCES := $(DIR_SOURCES) x.c
-endif
+# optional surface handlers
+SURFACE_HANDLER_$(NSFB_ABLE_AVAILABLE) += able.c
+SURFACE_HANDLER_$(NSFB_LINUX_AVAILABLE) += linux.c
+SURFACE_HANDLER_$(NSFB_SDL_AVAILABLE) += sdl.c
+SURFACE_HANDLER_$(NSFB_XCB_AVAILABLE) += x.c
+SURFACE_HANDLER_$(NSFB_VNC_AVAILABLE) += vnc.c
+SURFACE_HANDLER_$(NSFB_WLD_AVAILABLE) += wld.c
-ifeq ($(NSFB_VNC_AVAILABLE),yes)
- DIR_SOURCES := $(DIR_SOURCES) vnc.c
-endif
-
-ifeq ($(NSFB_WLD_AVAILABLE),yes)
- DIR_SOURCES := $(DIR_SOURCES) wl.c
-endif
+DIR_SOURCES := $(SURFACE_HANDLER_yes)
include $(NSBUILD)/Makefile.subdir
diff --git a/src/surface/wl.c b/src/surface/wl.c
deleted file mode 100644
index fbe26cf..0000000
--- a/src/surface/wl.c
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
- * Copyright 2009 Vincent Sanders <vince(a)simtec.co.uk>
- *
- * This file is part of libnsfb, http://www.netsurf-browser.org/
- * Licenced under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
- */
-
-#define _XOPEN_SOURCE 500
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-#include <xcb/xcb.h>
-#include <xcb/xcb_image.h>
-#include <xcb/xcb_atom.h>
-#include <xcb/xcb_icccm.h>
-#include <xcb/xcb_aux.h>
-#include <xcb/xcb_keysyms.h>
-
-#include "libnsfb.h"
-#include "libnsfb_event.h"
-#include "libnsfb_plot.h"
-#include "libnsfb_plot_util.h"
-
-#include "nsfb.h"
-#include "surface.h"
-#include "plot.h"
-#include "cursor.h"
-
-#if defined(NSFB_NEED_HINTS_ALLOC)
-static xcb_size_hints_t *
-xcb_alloc_size_hints(void)
-{
- return calloc(1, sizeof(xcb_size_hints_t));
-}
-
-static void
-xcb_free_size_hints(xcb_size_hints_t *hints)
-{
- free(hints);
-}
-#endif
-
-#if defined(NSFB_NEED_ICCCM_API_PREFIX)
-#define xcb_size_hints_set_max_size xcb_icccm_size_hints_set_max_size
-#define xcb_size_hints_set_min_size xcb_icccm_size_hints_set_min_size
-#define xcb_set_wm_size_hints xcb_icccm_set_wm_size_hints
-#endif
-
-#if (NSFB_XCBPROTO_MAJOR_VERSION > 1) || \
- (NSFB_XCBPROTO_MAJOR_VERSION == 1 && NSFB_XCBPROTO_MINOR_VERSION >= 6)
-#define WM_NORMAL_HINTS XCB_ATOM_WM_NORMAL_HINTS
-#endif
-
-#define X_BUTTON_LEFT 1
-#define X_BUTTON_MIDDLE 2
-#define X_BUTTON_RIGHT 3
-#define X_BUTTON_WHEELUP 4
-#define X_BUTTON_WHEELDOWN 5
-
-typedef struct xstate_s {
- xcb_connection_t *connection; /* The x server connection */
- xcb_screen_t *screen; /* The screen to put the window on */
- xcb_key_symbols_t *keysymbols; /* keysym mappings */
-
- xcb_shm_segment_info_t shminfo;
-
- xcb_image_t *image; /* The X image buffer */
-
- xcb_window_t window; /* The handle to the window */
- xcb_pixmap_t pmap; /* The handle to the backing pixmap */
- xcb_gcontext_t gc; /* The handle to the pixmap plotting graphics context */
- xcb_shm_seg_t segment; /* The handle to the image shared memory */
-} xstate_t;
-
-/* X keyboard codepage to nsfb mapping*/
-enum nsfb_key_code_e XCSKeyboardMap[256] = {
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_BACKSPACE, /* XK_BackSpace */
- NSFB_KEY_TAB, /* XK_Tab */
- NSFB_KEY_UNKNOWN, /* XK_Linefeed */
- NSFB_KEY_CLEAR, /* XK_Clear */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_RETURN, /* XK_Return */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x10 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_PAUSE, /* XK_Pause */
- NSFB_KEY_UNKNOWN, /* XK_Scroll_Lock */
- NSFB_KEY_UNKNOWN, /* XK_Sys_Req */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_ESCAPE, /* XK_Escape */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x20 */
- NSFB_KEY_UNKNOWN, /* XK_Multi_key */
- NSFB_KEY_UNKNOWN, /* XK_Kanji */
- NSFB_KEY_UNKNOWN, /* XK_Muhenkan */
- NSFB_KEY_UNKNOWN, /* XK_Henkan_Mode */
- NSFB_KEY_UNKNOWN, /* XK_Henkan */
- NSFB_KEY_UNKNOWN, /* XK_Romaji */
- NSFB_KEY_UNKNOWN, /* XK_Hiragana*/
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x30 */
- NSFB_KEY_UNKNOWN, /* XK_Eisu_toggle */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_Codeinput */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_SingleCandidate */
- NSFB_KEY_UNKNOWN, /* XK_MultipleCandidate */
- NSFB_KEY_UNKNOWN, /* XK_PreviousCandidate */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x40 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x50 */
- NSFB_KEY_HOME, /* XK_Home */
- NSFB_KEY_LEFT, /* XK_Left */
- NSFB_KEY_UP, /* XK_Up */
- NSFB_KEY_RIGHT, /* XK_Right */
- NSFB_KEY_DOWN, /* XK_Down */
- NSFB_KEY_PAGEUP, /* XK_Page_Up */
- NSFB_KEY_PAGEDOWN, /* XK_Page_Down */
- NSFB_KEY_END, /* XK_End */
- NSFB_KEY_UNKNOWN, /* XK_Begin */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x60 */
- NSFB_KEY_UNKNOWN, /* XK_Select */
- NSFB_KEY_UNKNOWN, /* XK_Print*/
- NSFB_KEY_UNKNOWN, /* XK_Execute*/
- NSFB_KEY_UNKNOWN, /* XK_Insert*/
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_Undo*/
- NSFB_KEY_UNKNOWN, /* XK_Redo */
- NSFB_KEY_UNKNOWN, /* XK_Menu */
- NSFB_KEY_UNKNOWN, /* XK_Find */
- NSFB_KEY_UNKNOWN, /* XK_Cancel */
- NSFB_KEY_UNKNOWN, /* XK_Help */
- NSFB_KEY_UNKNOWN, /* XK_Break*/
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x70 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_Mode_switch */
- NSFB_KEY_UNKNOWN, /* XK_Num_Lock */
- /* 0x80 */
- NSFB_KEY_UNKNOWN, /* XK_KP_Space */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_KP_Tab */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_KP_Enter */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0x90 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_KP_F1*/
- NSFB_KEY_UNKNOWN, /* XK_KP_F2*/
- NSFB_KEY_UNKNOWN, /* XK_KP_F3*/
- NSFB_KEY_UNKNOWN, /* XK_KP_F4*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Home*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Left*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Up*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Right*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Down*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Page_Up*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Page_Down*/
- NSFB_KEY_UNKNOWN, /* XK_KP_End*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Begin*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Insert*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Delete*/
- /* 0xa0 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_KP_Multiply*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Add*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Separator*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Subtract*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Decimal*/
- NSFB_KEY_UNKNOWN, /* XK_KP_Divide*/
- /* 0xb0 */
- NSFB_KEY_UNKNOWN, /* XK_KP_0 */
- NSFB_KEY_UNKNOWN, /* XK_KP_1 */
- NSFB_KEY_UNKNOWN, /* XK_KP_2 */
- NSFB_KEY_UNKNOWN, /* XK_KP_3 */
- NSFB_KEY_UNKNOWN, /* XK_KP_4 */
- NSFB_KEY_UNKNOWN, /* XK_KP_5 */
- NSFB_KEY_UNKNOWN, /* XK_KP_6 */
- NSFB_KEY_UNKNOWN, /* XK_KP_7 */
- NSFB_KEY_UNKNOWN, /* XK_KP_8 */
- NSFB_KEY_UNKNOWN, /* XK_KP_9 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_F1, /* XK_F1 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* XK_KP_Equal */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_F2, /* XK_F2 */
- /* 0xc0 */
- NSFB_KEY_F3, /* XK_F3*/
- NSFB_KEY_F4, /* XK_F4*/
- NSFB_KEY_F5, /* XK_F5*/
- NSFB_KEY_F6, /* XK_F6*/
- NSFB_KEY_F7, /* XK_F7*/
- NSFB_KEY_F8, /* XK_F8*/
- NSFB_KEY_F9, /* XK_F9*/
- NSFB_KEY_F10, /* XK_F10*/
- NSFB_KEY_F11, /* XK_F11*/
- NSFB_KEY_F12, /* XK_F12*/
- NSFB_KEY_F13, /* XK_F13 */
- NSFB_KEY_F14, /* XK_F14 */
- NSFB_KEY_F15, /* XK_F15 */
- NSFB_KEY_UNKNOWN, /* XK_F16 */
- NSFB_KEY_UNKNOWN, /* XK_F17 */
- NSFB_KEY_UNKNOWN, /* XK_F18*/
- /* 0xd0 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- /* 0xe0 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_LSHIFT, /* XK_Shift_L*/
- NSFB_KEY_RSHIFT, /* XK_Shift_R*/
- NSFB_KEY_UNKNOWN, /* XK_Control_L*/
- NSFB_KEY_UNKNOWN, /* XK_Control_R*/
- NSFB_KEY_UNKNOWN, /* XK_Caps_Lock*/
- NSFB_KEY_UNKNOWN, /* XK_Shift_Lock*/
- NSFB_KEY_UNKNOWN, /* XK_Meta_L*/
- NSFB_KEY_UNKNOWN, /* XK_Meta_R*/
- NSFB_KEY_UNKNOWN, /* XK_Alt_L */
- NSFB_KEY_UNKNOWN, /* XK_Alt_R*/
- NSFB_KEY_UNKNOWN, /* XK_Super_L*/
- NSFB_KEY_UNKNOWN, /* XK_Super_R*/
- NSFB_KEY_UNKNOWN, /* XK_Hyper_L*/
- NSFB_KEY_UNKNOWN, /* XK_Hyper_R*/
- NSFB_KEY_UNKNOWN, /* */
- /* 0xf0 */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
- NSFB_KEY_UNKNOWN, /* */
-};
-
-/* Convert an X keysym into a nsfb key code.
- *
- * Our approach is primarily to assume both codings are roughly ascii like.
- *
- * The Keysyms are defined in X11/keysymdef.h and our mapping for the
- * "keyboard" keys i.e. those from code set 255 is from there
- */
-static enum nsfb_key_code_e
-xkeysym_to_nsfbkeycode(xcb_keysym_t ks)
-{
- enum nsfb_key_code_e nsfb_key = NSFB_KEY_UNKNOWN;
- uint8_t codeset = (ks & 0xFF00) >> 8;
- uint8_t chrcode = ks & 0xFF;
-
- if (ks != XCB_NO_SYMBOL) {
-
- switch (codeset) {
- case 0x00: /* Latin 1 */
- case 0x01: /* Latin 2 */
- case 0x02: /* Latin 3 */
- case 0x03: /* Latin 4 */
- case 0x04: /* Katakana */
- case 0x05: /* Arabic */
- case 0x06: /* Cyrillic */
- case 0x07: /* Greek */
- case 0x08: /* Technical */
- case 0x0A: /* Publishing */
- case 0x0C: /* Hebrew */
- case 0x0D: /* Thai */
- /* this is somewhat incomplete, but the nsfb codes are lined up on
- * the ascii codes and x seems to have done similar
- */
- nsfb_key = (enum nsfb_key_code_e)chrcode;
- break;
-
- case 0xFF: /* Keyboard */
- nsfb_key = XCSKeyboardMap[chrcode];
- break;
- }
- }
-
- return nsfb_key;
-}
-/*
- static void
- set_palette(nsfb_t *nsfb)
- {
- X_Surface *x_screen = nsfb->surface_priv;
- X_Color palette[256];
- int rloop, gloop, bloop;
- int loop = 0;
-
- // build a linear R:3 G:3 B:2 colour cube palette.
- for (rloop = 0; rloop < 8; rloop++) {
- for (gloop = 0; gloop < 8; gloop++) {
- for (bloop = 0; bloop < 4; bloop++) {
- palette[loop].r = (rloop << 5) | (rloop << 2) | (rloop >> 1);
- palette[loop].g = (gloop << 5) | (gloop << 2) | (gloop >> 1);
- palette[loop].b = (bloop << 6) | (bloop << 4) | (bloop << 2) | (bloop);
- nsfb->palette[loop] = palette[loop].r |
- palette[loop].g << 8 |
- palette[loop].b << 16;
- loop++;
- }
- }
- }
-
- // Set palette
- //X_SetColors(x_screen, palette, 0, 256);
-
- }
-*/
-static int
-update_pixmap(xstate_t *xstate, int x, int y, int width, int height)
-{
- if (xstate->shminfo.shmseg == 0) {
- /* not using shared memory */
- xcb_put_image(xstate->connection,
- xstate->image->format,
- xstate->pmap,
- xstate->gc,
- xstate->image->width,
- height,
- 0,
- y,
- 0,
- xstate->image->depth,
- (height) * xstate->image->stride,
- xstate->image->data + (y * xstate->image->stride));
- } else {
- /* shared memory */
- xcb_image_shm_put(xstate->connection,
- xstate->pmap,
- xstate->gc,
- xstate->image,
- xstate->shminfo,
- x,y,
- x,y,
- width,height,0);
- }
-
- return 0;
-}
-
-static int
-update_and_redraw_pixmap(xstate_t *xstate, int x, int y, int width, int height)
-{
- update_pixmap(xstate, x, y, width, height);
-
- xcb_copy_area(xstate->connection,
- xstate->pmap,
- xstate->window,
- xstate->gc,
- x, y,
- x, y,
- width, height);
-
- xcb_flush(xstate->connection);
-
- return 0;
-}
-
-
-static bool
-xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
-{
- xstate_t *xstate = nsfb->surface_priv;
- nsfb_bbox_t allbox;
- struct nsfb_cursor_s *cursor = nsfb->cursor;
- uint8_t *srcptr;
- uint8_t *dstptr;
- int srcx = srcbox->x0;
- int srcy = srcbox->y0;
- int dstx = dstbox->x0;
- int dsty = dstbox->y0;
- int width = dstbox->x1 - dstbox->x0;
- int height = dstbox->y1 - dstbox->y0;
- int hloop;
-
- nsfb_plot_add_rect(srcbox, dstbox, &allbox);
-
- /* clear the cursor if its within the region to be altered */
- if ((cursor != NULL) &&
- (cursor->plotted == true) &&
- (nsfb_plot_bbox_intersect(&allbox, &cursor->loc))) {
-
- nsfb_cursor_clear(nsfb, cursor);
- update_pixmap(xstate,
- cursor->savloc.x0,
- cursor->savloc.y0,
- cursor->savloc.x1 - cursor->savloc.x0,
- cursor->savloc.y1 - cursor->savloc.y0);
-
- /* must sync here or local framebuffer and remote pixmap will not be
- * consistant
- */
- xcb_aux_sync(xstate->connection);
-
- }
-
- /* copy the area on the server */
- xcb_copy_area(xstate->connection,
- xstate->pmap,
- xstate->pmap,
- xstate->gc,
- srcbox->x0,
- srcbox->y0,
- dstbox->x0,
- dstbox->y0,
- srcbox->x1 - srcbox->x0,
- srcbox->y1 - srcbox->y0);
-
- /* do the copy in the local memory too */
- srcptr = (nsfb->ptr +
- (srcy * nsfb->linelen) +
- ((srcx * nsfb->bpp) / 8));
-
- dstptr = (nsfb->ptr +
- (dsty * nsfb->linelen) +
- ((dstx * nsfb->bpp) / 8));
-
- if (width == nsfb->width) {
- /* take shortcut and use memmove */
- memmove(dstptr, srcptr, (width * height * nsfb->bpp) / 8);
- } else {
- if (srcy > dsty) {
- for (hloop = height; hloop > 0; hloop--) {
- memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
- srcptr += nsfb->linelen;
- dstptr += nsfb->linelen;
- }
- } else {
- srcptr += height * nsfb->linelen;
- dstptr += height * nsfb->linelen;
- for (hloop = height; hloop > 0; hloop--) {
- srcptr -= nsfb->linelen;
- dstptr -= nsfb->linelen;
- memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
- }
- }
- }
-
- if ((cursor != NULL) &&
- (cursor->plotted == false)) {
- nsfb_cursor_plot(nsfb, cursor);
- }
-
- /* update the x window */
- xcb_copy_area(xstate->connection,
- xstate->pmap,
- xstate->window,
- xstate->gc,
- dstx, dsty,
- dstx, dsty,
- width, height);
-
- return true;
-
-}
-
-
-static int
-x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
-{
- if (nsfb->surface_priv != NULL)
- return -1; /* if were already initialised fail */
-
- nsfb->width = width;
- nsfb->height = height;
- nsfb->format = format;
-
- /* select default sw plotters for format */
- select_plotters(nsfb);
-
- nsfb->plotter_fns->copy = xcopy;
-
- return 0;
-}
-
-
-static xcb_format_t *
-find_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp)
-{
- const xcb_setup_t *setup = xcb_get_setup(c);
- xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
- xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
-
- for(; fmt != fmtend; ++fmt) {
- if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) {
- return fmt;
- }
- }
- return 0;
-}
-
-static xcb_image_t *
-create_shm_image(xstate_t *xstate, int width, int height, int bpp)
-{
- const xcb_setup_t *setup = xcb_get_setup(xstate->connection);
- unsigned char *image_data;
- xcb_format_t *fmt;
- int depth = bpp;
- uint32_t image_size;
- int shmid;
-
- xcb_shm_query_version_reply_t *rep;
- xcb_shm_query_version_cookie_t ck;
- xcb_void_cookie_t shm_attach_cookie;
- xcb_generic_error_t *generic_error;
-
- ck = xcb_shm_query_version(xstate->connection);
- rep = xcb_shm_query_version_reply(xstate->connection, ck , NULL);
- if (!rep) {
- fprintf (stderr, "Server has no shm support.\n");
- return NULL;
- }
-
- if ((rep->major_version < 1) ||
- (rep->major_version == 1 && rep->minor_version == 0)) {
- fprintf(stderr, "server SHM support is insufficient.\n");
- free(rep);
- return NULL;
- }
- free(rep);
-
- if (bpp == 32)
- depth = 24;
-
- fmt = find_format(xstate->connection, depth, bpp);
- if (fmt == NULL)
- return NULL;
-
- /* doing it this way ensures we deal with bpp smaller than 8 */
- image_size = (bpp * width * height) >> 3;
-
- /* get the shared memory segment */
- shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777);
- if (shmid == -1)
- return NULL;
-
- xstate->shminfo.shmid = shmid;
-
- xstate->shminfo.shmaddr = shmat(xstate->shminfo.shmid, 0, 0);
- image_data = xstate->shminfo.shmaddr;
-
- xstate->shminfo.shmseg = xcb_generate_id(xstate->connection);
- shm_attach_cookie = xcb_shm_attach_checked(xstate->connection,
- xstate->shminfo.shmseg,
- xstate->shminfo.shmid,
- 0);
- generic_error = xcb_request_check(xstate->connection, shm_attach_cookie);
-
- /* either there is an error and the shm us no longer needed, or it now
- * belongs to the x server - regardless release local reference to shared
- * memory segment
- */
- shmctl(xstate->shminfo.shmid, IPC_RMID, 0);
-
- if (generic_error != NULL) {
- /* unable to attach shm */
- xstate->shminfo.shmseg = 0;
-
- free(generic_error);
- return NULL;
- }
-
-
- return xcb_image_create(width,
- height,
- XCB_IMAGE_FORMAT_Z_PIXMAP,
- fmt->scanline_pad,
- fmt->depth,
- fmt->bits_per_pixel,
- 0,
- setup->image_byte_order,
- XCB_IMAGE_ORDER_LSB_FIRST,
- image_data,
- image_size,
- image_data);
-}
-
-
-static xcb_image_t *
-create_image(xcb_connection_t *c, int width, int height, int bpp)
-{
- const xcb_setup_t *setup = xcb_get_setup(c);
- unsigned char *image_data;
- xcb_format_t *fmt;
- int depth = bpp;
- uint32_t image_size;
-
- if (bpp == 32)
- depth = 24;
-
- fmt = find_format(c, depth, bpp);
- if (fmt == NULL)
- return NULL;
-
- /* doing it this way ensures we deal with bpp smaller than 8 */
- image_size = (bpp * width * height) >> 3;
-
- image_data = calloc(1, image_size);
- if (image_data == NULL)
- return NULL;
-
- return xcb_image_create(width,
- height,
- XCB_IMAGE_FORMAT_Z_PIXMAP,
- fmt->scanline_pad,
- fmt->depth,
- fmt->bits_per_pixel,
- 0,
- setup->image_byte_order,
- XCB_IMAGE_ORDER_LSB_FIRST,
- image_data,
- image_size,
- image_data);
-}
-
-/**
- * Create a blank cursor.
- * The empty pixmaps is leaked.
- *
- * @param conn xcb connection
- * @param scr xcb XCB screen
- */
-static xcb_cursor_t
-create_blank_cursor(xcb_connection_t *conn, const xcb_screen_t *scr)
-{
- xcb_cursor_t cur = xcb_generate_id(conn);
- xcb_pixmap_t pix = xcb_generate_id(conn);
- xcb_void_cookie_t ck;
- xcb_generic_error_t *err;
-
- ck = xcb_create_pixmap_checked (conn, 1, pix, scr->root, 1, 1);
- err = xcb_request_check (conn, ck);
- if (err) {
- fprintf (stderr, "Cannot create pixmap: %d", err->error_code);
- free (err);
- }
- ck = xcb_create_cursor_checked (conn, cur, pix, pix, 0, 0, 0, 0, 0, 0, 0, 0);
- err = xcb_request_check (conn, ck);
- if (err) {
- fprintf (stderr, "Cannot create cursor: %d", err->error_code);
- free (err);
- }
- return cur;
-}
-
-static int wl_initialise(nsfb_t *nsfb)
-{
-}
-
-static int x_initialise(nsfb_t *nsfb)
-{
- uint32_t mask;
- uint32_t values[3];
- xcb_size_hints_t *hints;
- xstate_t *xstate = nsfb->surface_priv;
- xcb_cursor_t blank_cursor;
-
- if (xstate != NULL)
- return -1; /* already initialised */
-
- /* sanity check bpp. */
- if ((nsfb->bpp != 32) && (nsfb->bpp != 16) && (nsfb->bpp != 8))
- return -1;
-
- xstate = calloc(1, sizeof(xstate_t));
- if (xstate == NULL)
- return -1; /* no memory */
-
- /* open connection with the server */
- xstate->connection = xcb_connect(NULL, NULL);
- if (xstate->connection == NULL) {
- fprintf(stderr, "Memory error opening display\n");
- free(xstate);
- return -1; /* no memory */
- }
-
- if (xcb_connection_has_error(xstate->connection) != 0) {
- fprintf(stderr, "Error opening display\n");
- free(xstate);
- return -1; /* no memory */
- }
-
- /* get screen */
- xstate->screen = xcb_setup_roots_iterator(xcb_get_setup(xstate->connection)).data;
-
- /* create image */
- xstate->image = create_shm_image(xstate, nsfb->width, nsfb->height, nsfb->bpp);
-
- if (xstate->image == NULL)
- xstate->image = create_image(xstate->connection, nsfb->width, nsfb->height, nsfb->bpp);
-
- if (xstate->image == NULL) {
- fprintf(stderr, "Unable to create image\n");
- free(xstate);
- xcb_disconnect(xstate->connection);
- return -1;
- }
-
- /* ensure plotting information is stored */
- nsfb->surface_priv = xstate;
- nsfb->ptr = xstate->image->data;
- nsfb->linelen = xstate->image->stride;
-
- /* get blank cursor */
- blank_cursor = create_blank_cursor(xstate->connection, xstate->screen);
-
- /* get keysymbol maps */
- xstate->keysymbols = xcb_key_symbols_alloc(xstate->connection);
-
- /* create window */
- mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
- values[0] = xstate->screen->white_pixel;
- values[1] = XCB_EVENT_MASK_EXPOSURE |
- XCB_EVENT_MASK_KEY_PRESS |
- XCB_EVENT_MASK_KEY_RELEASE |
- XCB_EVENT_MASK_BUTTON_PRESS |
- XCB_EVENT_MASK_BUTTON_RELEASE |
- XCB_EVENT_MASK_POINTER_MOTION;
- values[2] = blank_cursor;
-
- xstate->window = xcb_generate_id(xstate->connection);
- xcb_create_window (xstate->connection,
- XCB_COPY_FROM_PARENT,
- xstate->window,
- xstate->screen->root,
- 0, 0, xstate->image->width, xstate->image->height, 1,
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
- xstate->screen->root_visual,
- mask, values);
- /* set size hits on window */
- hints = xcb_alloc_size_hints();
- xcb_size_hints_set_max_size(hints, xstate->image->width, xstate->image->height);
- xcb_size_hints_set_min_size(hints, xstate->image->width, xstate->image->height);
- xcb_set_wm_size_hints(xstate->connection, xstate->window, WM_NORMAL_HINTS, hints);
- xcb_free_size_hints(hints);
-
- /* create backing pixmap */
- xstate->pmap = xcb_generate_id(xstate->connection);
- xcb_create_pixmap(xstate->connection, 24, xstate->pmap, xstate->window, xstate->image->width, xstate->image->height);
-
- /* create pixmap plot gc */
- mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
- values[0] = xstate->screen->black_pixel;
- values[1] = 0xffffff;
-
- xstate->gc = xcb_generate_id (xstate->connection);
- xcb_create_gc(xstate->connection, xstate->gc, xstate->pmap, mask, values);
-
- /* if (nsfb->bpp == 8)
- set_palette(nsfb);
- */
-
- /* put the image into the pixmap */
- update_and_redraw_pixmap(xstate, 0, 0, xstate->image->width, xstate->image->height);
-
-
- /* show the window */
- xcb_map_window (xstate->connection, xstate->window);
- xcb_flush(xstate->connection);
-
- return 0;
-}
-
-static int x_finalise(nsfb_t *nsfb)
-{
- xstate_t *xstate = nsfb->surface_priv;
- if (xstate == NULL)
- return 0;
-
- xcb_key_symbols_free(xstate->keysymbols);
-
- /* free pixmap */
- xcb_free_pixmap(xstate->connection, xstate->pmap);
-
- /* close connection to server */
- xcb_disconnect(xstate->connection);
-
- return 0;
-}
-
-static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
-{
- xcb_generic_event_t *e;
- xcb_expose_event_t *ee;
- xcb_motion_notify_event_t *emn;
- xcb_button_press_event_t *ebp;
- xcb_key_press_event_t *ekp;
- xcb_key_press_event_t *ekr;
- xstate_t *xstate = nsfb->surface_priv;
-
- if (xstate == NULL)
- return false;
-
- xcb_flush(xstate->connection);
-
- /* try and retrive an event immediately */
- e = xcb_poll_for_event(xstate->connection);
-
- if ((e == NULL) && (timeout != 0)) {
- if (timeout > 0) {
- int confd;
- fd_set rfds;
- struct timeval tv;
- int retval;
-
- confd = xcb_get_file_descriptor(xstate->connection);
- FD_ZERO(&rfds);
- FD_SET(confd, &rfds);
-
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = timeout % 1000;
-
- retval = select(confd + 1, &rfds, NULL, NULL, &tv);
- if (retval == 0) {
- /* timeout, nothing happened */
- event->type = NSFB_EVENT_CONTROL;
- event->value.controlcode = NSFB_CONTROL_TIMEOUT;
- return true;
- }
- }
- e = xcb_wait_for_event(xstate->connection);
- }
-
- if (e == NULL) {
- if (xcb_connection_has_error(xstate->connection) != 0) {
- /* connection closed quiting time */
- event->type = NSFB_EVENT_CONTROL;
- event->value.controlcode = NSFB_CONTROL_QUIT;
- return true;
- } else {
- return false; /* no event */
- }
- }
-
- event->type = NSFB_EVENT_NONE;
-
- switch (e->response_type) {
- case XCB_EXPOSE:
- ee = (xcb_expose_event_t *)e;
- xcb_copy_area(xstate->connection,
- xstate->pmap,
- xstate->window,
- xstate->gc,
- ee->x, ee->y,
- ee->x, ee->y,
- ee->width, ee->height);
- xcb_flush (xstate->connection);
- break;
-
- case XCB_MOTION_NOTIFY:
- emn = (xcb_motion_notify_event_t *)e;
- event->type = NSFB_EVENT_MOVE_ABSOLUTE;
- event->value.vector.x = emn->event_x;
- event->value.vector.y = emn->event_y;
- event->value.vector.z = 0;
- break;
-
-
- case XCB_BUTTON_PRESS:
- ebp = (xcb_button_press_event_t *)e;
- event->type = NSFB_EVENT_KEY_DOWN;
-
- switch (ebp->detail) {
-
- case X_BUTTON_LEFT:
- event->value.keycode = NSFB_KEY_MOUSE_1;
- break;
-
- case X_BUTTON_MIDDLE:
- event->value.keycode = NSFB_KEY_MOUSE_2;
- break;
-
- case X_BUTTON_RIGHT:
- event->value.keycode = NSFB_KEY_MOUSE_3;
- break;
-
- case X_BUTTON_WHEELUP:
- event->value.keycode = NSFB_KEY_MOUSE_4;
- break;
-
- case X_BUTTON_WHEELDOWN:
- event->value.keycode = NSFB_KEY_MOUSE_5;
- break;
- }
- break;
-
- case XCB_BUTTON_RELEASE:
- ebp = (xcb_button_press_event_t *)e;
- event->type = NSFB_EVENT_KEY_UP;
-
- switch (ebp->detail) {
-
- case X_BUTTON_LEFT:
- event->value.keycode = NSFB_KEY_MOUSE_1;
- break;
-
- case X_BUTTON_MIDDLE:
- event->value.keycode = NSFB_KEY_MOUSE_2;
- break;
-
- case X_BUTTON_RIGHT:
- event->value.keycode = NSFB_KEY_MOUSE_3;
- break;
-
- case X_BUTTON_WHEELUP:
- event->value.keycode = NSFB_KEY_MOUSE_4;
- break;
-
- case X_BUTTON_WHEELDOWN:
- event->value.keycode = NSFB_KEY_MOUSE_5;
- break;
- }
- break;
-
-
- case XCB_KEY_PRESS:
- ekp = (xcb_key_press_event_t *)e;
- event->type = NSFB_EVENT_KEY_DOWN;
- event->value.keycode = xkeysym_to_nsfbkeycode(xcb_key_symbols_get_keysym(xstate->keysymbols, ekp->detail, 0));
- break;
-
- case XCB_KEY_RELEASE:
- ekr = (xcb_key_release_event_t *)e;
- event->type = NSFB_EVENT_KEY_UP;
- event->value.keycode = xkeysym_to_nsfbkeycode(xcb_key_symbols_get_keysym(xstate->keysymbols, ekr->detail, 0));
- break;
-
- }
-
- free(e);
-
- return true;
-}
-
-static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
-{
- struct nsfb_cursor_s *cursor = nsfb->cursor;
-
- if ((cursor != NULL) &&
- (cursor->plotted == true) &&
- (nsfb_plot_bbox_intersect(box, &cursor->loc))) {
- nsfb_cursor_clear(nsfb, cursor);
- }
- return 0;
-}
-
-
-
-static int
-x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
-{
- xstate_t *xstate = nsfb->surface_priv;
- nsfb_bbox_t redraw;
- nsfb_bbox_t fbarea;
-
- if ((cursor != NULL) && (cursor->plotted == true)) {
-
- nsfb_plot_add_rect(&cursor->savloc, &cursor->loc, &redraw);
-
- /* screen area */
- fbarea.x0 = 0;
- fbarea.y0 = 0;
- fbarea.x1 = nsfb->width;
- fbarea.y1 = nsfb->height;
-
- nsfb_plot_clip(&fbarea, &redraw);
-
- nsfb_cursor_clear(nsfb, cursor);
-
- nsfb_cursor_plot(nsfb, cursor);
-
- /* TODO: This is hediously ineficient - should keep the pointer image
- * as a pixmap and plot server side
- */
- update_and_redraw_pixmap(xstate, redraw.x0, redraw.y0, redraw.x1 - redraw.x0, redraw.y1 - redraw.y0);
-
- }
- return true;
-}
-
-
-static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
-{
- xstate_t *xstate = nsfb->surface_priv;
- struct nsfb_cursor_s *cursor = nsfb->cursor;
-
- if ((cursor != NULL) &&
- (cursor->plotted == false)) {
- nsfb_cursor_plot(nsfb, cursor);
- }
-
- update_and_redraw_pixmap(xstate, box->x0, box->y0, box->x1 - box->x0, box->y1 - box->y0);
-
- return 0;
-}
-
-const nsfb_surface_rtns_t wl_rtns = {
- .initialise = x_initialise,
- .finalise = x_finalise,
- .input = x_input,
- .claim = x_claim,
- .update = x_update,
- .cursor = x_cursor,
- .geometry = x_set_geometry,
-};
-
-NSFB_SURFACE_DEF(wl, NSFB_SURFACE_WL, &wl_rtns)
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
diff --git a/src/surface/wld.c b/src/surface/wld.c
new file mode 100644
index 0000000..d450738
--- /dev/null
+++ b/src/surface/wld.c
@@ -0,0 +1,1517 @@
+/*
+ * Copyright 2009 Vincent Sanders <vince(a)simtec.co.uk>
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+#define _XOPEN_SOURCE 500
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_image.h>
+#include <xcb/xcb_atom.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/xcb_keysyms.h>
+
+#include "libnsfb.h"
+#include "libnsfb_event.h"
+#include "libnsfb_plot.h"
+#include "libnsfb_plot_util.h"
+
+#include "nsfb.h"
+#include "surface.h"
+#include "plot.h"
+#include "cursor.h"
+
+#if defined(NSFB_NEED_HINTS_ALLOC)
+static xcb_size_hints_t *
+xcb_alloc_size_hints(void)
+{
+ return calloc(1, sizeof(xcb_size_hints_t));
+}
+
+static void
+xcb_free_size_hints(xcb_size_hints_t *hints)
+{
+ free(hints);
+}
+#endif
+
+#if defined(NSFB_NEED_ICCCM_API_PREFIX)
+#define xcb_size_hints_set_max_size xcb_icccm_size_hints_set_max_size
+#define xcb_size_hints_set_min_size xcb_icccm_size_hints_set_min_size
+#define xcb_set_wm_size_hints xcb_icccm_set_wm_size_hints
+#endif
+
+#if (NSFB_XCBPROTO_MAJOR_VERSION > 1) || \
+ (NSFB_XCBPROTO_MAJOR_VERSION == 1 && NSFB_XCBPROTO_MINOR_VERSION >= 6)
+#define WM_NORMAL_HINTS XCB_ATOM_WM_NORMAL_HINTS
+#endif
+
+#define X_BUTTON_LEFT 1
+#define X_BUTTON_MIDDLE 2
+#define X_BUTTON_RIGHT 3
+#define X_BUTTON_WHEELUP 4
+#define X_BUTTON_WHEELDOWN 5
+
+typedef struct xstate_s {
+ xcb_connection_t *connection; /* The x server connection */
+ xcb_screen_t *screen; /* The screen to put the window on */
+ xcb_key_symbols_t *keysymbols; /* keysym mappings */
+
+ xcb_shm_segment_info_t shminfo;
+
+ xcb_image_t *image; /* The X image buffer */
+
+ xcb_window_t window; /* The handle to the window */
+ xcb_pixmap_t pmap; /* The handle to the backing pixmap */
+ xcb_gcontext_t gc; /* The handle to the pixmap plotting graphics context */
+ xcb_shm_seg_t segment; /* The handle to the image shared memory */
+} xstate_t;
+
+/* X keyboard codepage to nsfb mapping*/
+static enum nsfb_key_code_e XCSKeyboardMap[256] = {
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_BACKSPACE, /* XK_BackSpace */
+ NSFB_KEY_TAB, /* XK_Tab */
+ NSFB_KEY_UNKNOWN, /* XK_Linefeed */
+ NSFB_KEY_CLEAR, /* XK_Clear */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_RETURN, /* XK_Return */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x10 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_PAUSE, /* XK_Pause */
+ NSFB_KEY_UNKNOWN, /* XK_Scroll_Lock */
+ NSFB_KEY_UNKNOWN, /* XK_Sys_Req */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_ESCAPE, /* XK_Escape */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x20 */
+ NSFB_KEY_UNKNOWN, /* XK_Multi_key */
+ NSFB_KEY_UNKNOWN, /* XK_Kanji */
+ NSFB_KEY_UNKNOWN, /* XK_Muhenkan */
+ NSFB_KEY_UNKNOWN, /* XK_Henkan_Mode */
+ NSFB_KEY_UNKNOWN, /* XK_Henkan */
+ NSFB_KEY_UNKNOWN, /* XK_Romaji */
+ NSFB_KEY_UNKNOWN, /* XK_Hiragana*/
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x30 */
+ NSFB_KEY_UNKNOWN, /* XK_Eisu_toggle */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_Codeinput */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_SingleCandidate */
+ NSFB_KEY_UNKNOWN, /* XK_MultipleCandidate */
+ NSFB_KEY_UNKNOWN, /* XK_PreviousCandidate */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x40 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x50 */
+ NSFB_KEY_HOME, /* XK_Home */
+ NSFB_KEY_LEFT, /* XK_Left */
+ NSFB_KEY_UP, /* XK_Up */
+ NSFB_KEY_RIGHT, /* XK_Right */
+ NSFB_KEY_DOWN, /* XK_Down */
+ NSFB_KEY_PAGEUP, /* XK_Page_Up */
+ NSFB_KEY_PAGEDOWN, /* XK_Page_Down */
+ NSFB_KEY_END, /* XK_End */
+ NSFB_KEY_UNKNOWN, /* XK_Begin */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x60 */
+ NSFB_KEY_UNKNOWN, /* XK_Select */
+ NSFB_KEY_UNKNOWN, /* XK_Print*/
+ NSFB_KEY_UNKNOWN, /* XK_Execute*/
+ NSFB_KEY_UNKNOWN, /* XK_Insert*/
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_Undo*/
+ NSFB_KEY_UNKNOWN, /* XK_Redo */
+ NSFB_KEY_UNKNOWN, /* XK_Menu */
+ NSFB_KEY_UNKNOWN, /* XK_Find */
+ NSFB_KEY_UNKNOWN, /* XK_Cancel */
+ NSFB_KEY_UNKNOWN, /* XK_Help */
+ NSFB_KEY_UNKNOWN, /* XK_Break*/
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x70 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_Mode_switch */
+ NSFB_KEY_UNKNOWN, /* XK_Num_Lock */
+ /* 0x80 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Space */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Tab */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Enter */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x90 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_F1*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_F2*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_F3*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_F4*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Home*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Left*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Up*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Right*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Down*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Page_Up*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Page_Down*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_End*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Begin*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Insert*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Delete*/
+ /* 0xa0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Multiply*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Add*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Separator*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Subtract*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Decimal*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Divide*/
+ /* 0xb0 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_0 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_1 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_2 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_3 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_4 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_5 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_6 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_7 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_8 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_9 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_F1, /* XK_F1 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Equal */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_F2, /* XK_F2 */
+ /* 0xc0 */
+ NSFB_KEY_F3, /* XK_F3*/
+ NSFB_KEY_F4, /* XK_F4*/
+ NSFB_KEY_F5, /* XK_F5*/
+ NSFB_KEY_F6, /* XK_F6*/
+ NSFB_KEY_F7, /* XK_F7*/
+ NSFB_KEY_F8, /* XK_F8*/
+ NSFB_KEY_F9, /* XK_F9*/
+ NSFB_KEY_F10, /* XK_F10*/
+ NSFB_KEY_F11, /* XK_F11*/
+ NSFB_KEY_F12, /* XK_F12*/
+ NSFB_KEY_F13, /* XK_F13 */
+ NSFB_KEY_F14, /* XK_F14 */
+ NSFB_KEY_F15, /* XK_F15 */
+ NSFB_KEY_UNKNOWN, /* XK_F16 */
+ NSFB_KEY_UNKNOWN, /* XK_F17 */
+ NSFB_KEY_UNKNOWN, /* XK_F18*/
+ /* 0xd0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0xe0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_LSHIFT, /* XK_Shift_L*/
+ NSFB_KEY_RSHIFT, /* XK_Shift_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Control_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Control_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Caps_Lock*/
+ NSFB_KEY_UNKNOWN, /* XK_Shift_Lock*/
+ NSFB_KEY_UNKNOWN, /* XK_Meta_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Meta_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Alt_L */
+ NSFB_KEY_UNKNOWN, /* XK_Alt_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Super_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Super_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Hyper_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Hyper_R*/
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0xf0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+};
+
+/* Convert an X keysym into a nsfb key code.
+ *
+ * Our approach is primarily to assume both codings are roughly ascii like.
+ *
+ * The Keysyms are defined in X11/keysymdef.h and our mapping for the
+ * "keyboard" keys i.e. those from code set 255 is from there
+ */
+static enum nsfb_key_code_e
+xkeysym_to_nsfbkeycode(xcb_keysym_t ks)
+{
+ enum nsfb_key_code_e nsfb_key = NSFB_KEY_UNKNOWN;
+ uint8_t codeset = (ks & 0xFF00) >> 8;
+ uint8_t chrcode = ks & 0xFF;
+
+ if (ks != XCB_NO_SYMBOL) {
+
+ switch (codeset) {
+ case 0x00: /* Latin 1 */
+ case 0x01: /* Latin 2 */
+ case 0x02: /* Latin 3 */
+ case 0x03: /* Latin 4 */
+ case 0x04: /* Katakana */
+ case 0x05: /* Arabic */
+ case 0x06: /* Cyrillic */
+ case 0x07: /* Greek */
+ case 0x08: /* Technical */
+ case 0x0A: /* Publishing */
+ case 0x0C: /* Hebrew */
+ case 0x0D: /* Thai */
+ /* this is somewhat incomplete, but the nsfb codes are lined up on
+ * the ascii codes and x seems to have done similar
+ */
+ nsfb_key = (enum nsfb_key_code_e)chrcode;
+ break;
+
+ case 0xFF: /* Keyboard */
+ nsfb_key = XCSKeyboardMap[chrcode];
+ break;
+ }
+ }
+
+ return nsfb_key;
+}
+/*
+ static void
+ set_palette(nsfb_t *nsfb)
+ {
+ X_Surface *x_screen = nsfb->surface_priv;
+ X_Color palette[256];
+ int rloop, gloop, bloop;
+ int loop = 0;
+
+ // build a linear R:3 G:3 B:2 colour cube palette.
+ for (rloop = 0; rloop < 8; rloop++) {
+ for (gloop = 0; gloop < 8; gloop++) {
+ for (bloop = 0; bloop < 4; bloop++) {
+ palette[loop].r = (rloop << 5) | (rloop << 2) | (rloop >> 1);
+ palette[loop].g = (gloop << 5) | (gloop << 2) | (gloop >> 1);
+ palette[loop].b = (bloop << 6) | (bloop << 4) | (bloop << 2) | (bloop);
+ nsfb->palette[loop] = palette[loop].r |
+ palette[loop].g << 8 |
+ palette[loop].b << 16;
+ loop++;
+ }
+ }
+ }
+
+ // Set palette
+ //X_SetColors(x_screen, palette, 0, 256);
+
+ }
+*/
+static int
+update_pixmap(xstate_t *xstate, int x, int y, int width, int height)
+{
+ if (xstate->shminfo.shmseg == 0) {
+ /* not using shared memory */
+ xcb_put_image(xstate->connection,
+ xstate->image->format,
+ xstate->pmap,
+ xstate->gc,
+ xstate->image->width,
+ height,
+ 0,
+ y,
+ 0,
+ xstate->image->depth,
+ (height) * xstate->image->stride,
+ xstate->image->data + (y * xstate->image->stride));
+ } else {
+ /* shared memory */
+ xcb_image_shm_put(xstate->connection,
+ xstate->pmap,
+ xstate->gc,
+ xstate->image,
+ xstate->shminfo,
+ x,y,
+ x,y,
+ width,height,0);
+ }
+
+ return 0;
+}
+
+static int
+update_and_redraw_pixmap(xstate_t *xstate, int x, int y, int width, int height)
+{
+ update_pixmap(xstate, x, y, width, height);
+
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->window,
+ xstate->gc,
+ x, y,
+ x, y,
+ width, height);
+
+ xcb_flush(xstate->connection);
+
+ return 0;
+}
+
+
+static bool
+xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ nsfb_bbox_t allbox;
+ struct nsfb_cursor_s *cursor = nsfb->cursor;
+ uint8_t *srcptr;
+ uint8_t *dstptr;
+ int srcx = srcbox->x0;
+ int srcy = srcbox->y0;
+ int dstx = dstbox->x0;
+ int dsty = dstbox->y0;
+ int width = dstbox->x1 - dstbox->x0;
+ int height = dstbox->y1 - dstbox->y0;
+ int hloop;
+
+ nsfb_plot_add_rect(srcbox, dstbox, &allbox);
+
+ /* clear the cursor if its within the region to be altered */
+ if ((cursor != NULL) &&
+ (cursor->plotted == true) &&
+ (nsfb_plot_bbox_intersect(&allbox, &cursor->loc))) {
+
+ nsfb_cursor_clear(nsfb, cursor);
+ update_pixmap(xstate,
+ cursor->savloc.x0,
+ cursor->savloc.y0,
+ cursor->savloc.x1 - cursor->savloc.x0,
+ cursor->savloc.y1 - cursor->savloc.y0);
+
+ /* must sync here or local framebuffer and remote pixmap will not be
+ * consistant
+ */
+ xcb_aux_sync(xstate->connection);
+
+ }
+
+ /* copy the area on the server */
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->pmap,
+ xstate->gc,
+ srcbox->x0,
+ srcbox->y0,
+ dstbox->x0,
+ dstbox->y0,
+ srcbox->x1 - srcbox->x0,
+ srcbox->y1 - srcbox->y0);
+
+ /* do the copy in the local memory too */
+ srcptr = (nsfb->ptr +
+ (srcy * nsfb->linelen) +
+ ((srcx * nsfb->bpp) / 8));
+
+ dstptr = (nsfb->ptr +
+ (dsty * nsfb->linelen) +
+ ((dstx * nsfb->bpp) / 8));
+
+ if (width == nsfb->width) {
+ /* take shortcut and use memmove */
+ memmove(dstptr, srcptr, (width * height * nsfb->bpp) / 8);
+ } else {
+ if (srcy > dsty) {
+ for (hloop = height; hloop > 0; hloop--) {
+ memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
+ srcptr += nsfb->linelen;
+ dstptr += nsfb->linelen;
+ }
+ } else {
+ srcptr += height * nsfb->linelen;
+ dstptr += height * nsfb->linelen;
+ for (hloop = height; hloop > 0; hloop--) {
+ srcptr -= nsfb->linelen;
+ dstptr -= nsfb->linelen;
+ memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
+ }
+ }
+ }
+
+ if ((cursor != NULL) &&
+ (cursor->plotted == false)) {
+ nsfb_cursor_plot(nsfb, cursor);
+ }
+
+ /* update the x window */
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->window,
+ xstate->gc,
+ dstx, dsty,
+ dstx, dsty,
+ width, height);
+
+ return true;
+
+}
+
+static int
+wld_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
+{
+}
+
+static int
+x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
+{
+ if (nsfb->surface_priv != NULL)
+ return -1; /* if were already initialised fail */
+
+ nsfb->width = width;
+ nsfb->height = height;
+ nsfb->format = format;
+
+ /* select default sw plotters for format */
+ select_plotters(nsfb);
+
+ nsfb->plotter_fns->copy = xcopy;
+
+ return 0;
+}
+
+
+static xcb_format_t *
+find_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp)
+{
+ const xcb_setup_t *setup = xcb_get_setup(c);
+ xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
+ xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
+
+ for(; fmt != fmtend; ++fmt) {
+ if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) {
+ return fmt;
+ }
+ }
+ return 0;
+}
+
+static xcb_image_t *
+create_shm_image(xstate_t *xstate, int width, int height, int bpp)
+{
+ const xcb_setup_t *setup = xcb_get_setup(xstate->connection);
+ unsigned char *image_data;
+ xcb_format_t *fmt;
+ int depth = bpp;
+ uint32_t image_size;
+ int shmid;
+
+ xcb_shm_query_version_reply_t *rep;
+ xcb_shm_query_version_cookie_t ck;
+ xcb_void_cookie_t shm_attach_cookie;
+ xcb_generic_error_t *generic_error;
+
+ ck = xcb_shm_query_version(xstate->connection);
+ rep = xcb_shm_query_version_reply(xstate->connection, ck , NULL);
+ if (!rep) {
+ fprintf (stderr, "Server has no shm support.\n");
+ return NULL;
+ }
+
+ if ((rep->major_version < 1) ||
+ (rep->major_version == 1 && rep->minor_version == 0)) {
+ fprintf(stderr, "server SHM support is insufficient.\n");
+ free(rep);
+ return NULL;
+ }
+ free(rep);
+
+ if (bpp == 32)
+ depth = 24;
+
+ fmt = find_format(xstate->connection, depth, bpp);
+ if (fmt == NULL)
+ return NULL;
+
+ /* doing it this way ensures we deal with bpp smaller than 8 */
+ image_size = (bpp * width * height) >> 3;
+
+ /* get the shared memory segment */
+ shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777);
+ if (shmid == -1)
+ return NULL;
+
+ xstate->shminfo.shmid = shmid;
+
+ xstate->shminfo.shmaddr = shmat(xstate->shminfo.shmid, 0, 0);
+ image_data = xstate->shminfo.shmaddr;
+
+ xstate->shminfo.shmseg = xcb_generate_id(xstate->connection);
+ shm_attach_cookie = xcb_shm_attach_checked(xstate->connection,
+ xstate->shminfo.shmseg,
+ xstate->shminfo.shmid,
+ 0);
+ generic_error = xcb_request_check(xstate->connection, shm_attach_cookie);
+
+ /* either there is an error and the shm us no longer needed, or it now
+ * belongs to the x server - regardless release local reference to shared
+ * memory segment
+ */
+ shmctl(xstate->shminfo.shmid, IPC_RMID, 0);
+
+ if (generic_error != NULL) {
+ /* unable to attach shm */
+ xstate->shminfo.shmseg = 0;
+
+ free(generic_error);
+ return NULL;
+ }
+
+
+ return xcb_image_create(width,
+ height,
+ XCB_IMAGE_FORMAT_Z_PIXMAP,
+ fmt->scanline_pad,
+ fmt->depth,
+ fmt->bits_per_pixel,
+ 0,
+ setup->image_byte_order,
+ XCB_IMAGE_ORDER_LSB_FIRST,
+ image_data,
+ image_size,
+ image_data);
+}
+
+
+static xcb_image_t *
+create_image(xcb_connection_t *c, int width, int height, int bpp)
+{
+ const xcb_setup_t *setup = xcb_get_setup(c);
+ unsigned char *image_data;
+ xcb_format_t *fmt;
+ int depth = bpp;
+ uint32_t image_size;
+
+ if (bpp == 32)
+ depth = 24;
+
+ fmt = find_format(c, depth, bpp);
+ if (fmt == NULL)
+ return NULL;
+
+ /* doing it this way ensures we deal with bpp smaller than 8 */
+ image_size = (bpp * width * height) >> 3;
+
+ image_data = calloc(1, image_size);
+ if (image_data == NULL)
+ return NULL;
+
+ return xcb_image_create(width,
+ height,
+ XCB_IMAGE_FORMAT_Z_PIXMAP,
+ fmt->scanline_pad,
+ fmt->depth,
+ fmt->bits_per_pixel,
+ 0,
+ setup->image_byte_order,
+ XCB_IMAGE_ORDER_LSB_FIRST,
+ image_data,
+ image_size,
+ image_data);
+}
+
+/**
+ * Create a blank cursor.
+ * The empty pixmaps is leaked.
+ *
+ * @param conn xcb connection
+ * @param scr xcb XCB screen
+ */
+static xcb_cursor_t
+create_blank_cursor(xcb_connection_t *conn, const xcb_screen_t *scr)
+{
+ xcb_cursor_t cur = xcb_generate_id(conn);
+ xcb_pixmap_t pix = xcb_generate_id(conn);
+ xcb_void_cookie_t ck;
+ xcb_generic_error_t *err;
+
+ ck = xcb_create_pixmap_checked (conn, 1, pix, scr->root, 1, 1);
+ err = xcb_request_check (conn, ck);
+ if (err) {
+ fprintf (stderr, "Cannot create pixmap: %d", err->error_code);
+ free (err);
+ }
+ ck = xcb_create_cursor_checked (conn, cur, pix, pix, 0, 0, 0, 0, 0, 0, 0, 0);
+ err = xcb_request_check (conn, ck);
+ if (err) {
+ fprintf (stderr, "Cannot create cursor: %d", err->error_code);
+ free (err);
+ }
+ return cur;
+}
+
+/** structure for display, registry and other global objects that
+ * should be cached when connecting to a wayland instance
+ */
+struct wld_connection {
+ struct wl_display *display; /**< connection object */
+ struct wl_registry *registry; /**< registry object */
+
+ /** compositor object, available once teh registry messages have
+ * been processed
+ */
+ struct wl_compositor *compositor;
+
+ /** shell object, available once the registry messages have been
+ * processed
+ */
+ struct wl_shell *shell;
+
+ /** shared memory object, available once the registry messages
+ * have been processed
+ */
+ struct wl_shm *shm;
+
+ /** shared memory formats available */
+ uint32_t shm_formats;
+};
+
+
+/** shared memory interface format available callback
+ *
+ * @param ctx context from when listener was added.
+ * @param wl_shm The shared memory object.
+ * @param format The available shared memory format. Found in
+ * wayland-client-protocol.h there are currently only two
+ * formats available (A|X)RGB8888 so using a bitfield is ok.
+ */
+static void
+shm_format(void *ctx, struct wl_shm *wl_shm, uint32_t format)
+{
+ struct wld_connection* connection = ctx;
+
+ connection->shm_formats |= (1 << format);
+}
+
+/** shared memory interface callback handlers */
+struct wl_shm_listener shm_listenter = {
+ shm_format
+};
+
+
+/** registry global addition callback
+ *
+ * @param ctx context from when listener was added
+ */
+static void
+registry_handle_global(void *ctx,
+ struct wl_registry *registry,
+ uint32_t id,
+ const char *interface,
+ uint32_t version)
+{
+ struct wld_connection* connection = ctx;
+
+ /* process new interfaces appearing on the global registry */
+
+ if (strcmp(interface, "wl_compositor") == 0) {
+ /* compositor interface is available. Bind the interface */
+ connection->compositor = wl_registry_bind(registry,
+ id,
+ &wl_compositor_interface,
+ 1);
+
+ } else if (strcmp(interface, "wl_shell") == 0) {
+ /* shell interface is available. Bind the interface */
+ connection->shell = wl_registry_bind(registry,
+ id,
+ &wl_shell_interface,
+ 1);
+
+ } else if (strcmp(interface, "wl_shm") == 0) {
+ /* shared memory interface is available. Bind the interface
+ * and add a listener for the shared memory callbacks
+ */
+ connection->shm = wl_registry_bind(registry,
+ id,
+ &wl_shm_interface,
+ 1);
+ if (connection->shm != NULL) {
+ connection->shm_formats = 0;
+ wl_shm_add_listener(connection->shm, &shm_listenter, connection);
+ }
+ }
+}
+
+/** registry global removal callback */
+static void
+registry_handle_global_remove(void *data,
+ struct wl_registry *registry,
+ uint32_t name)
+{
+}
+
+/** registry global callback handlers */
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ registry_handle_global_remove
+};
+
+
+/** construct a new connection to the wayland instance and aquire all
+ * necessary global objects
+ */
+static struct wld_connection*
+new_connection(void)
+{
+ struct wld_connection* connection;
+
+ connection = calloc(1, sizeof(struct wld_connection));
+
+ if (connection == NULL) {
+ return NULL;
+ }
+
+ /* make a connection to the wayland server */
+ connection->display = wl_display_connect(NULL);
+ if (connection->display == NULL) {
+ fprintf(stderr, "Unable to open display\n");
+ free(connection);
+ return NULL;
+ }
+
+ /* create the registry object and attach its callback handlers */
+ connection->registry = wl_display_get_registry(connection->display);
+ if (connection->registry == NULL) {
+ fprintf(stderr, "Unable create registry\n");
+ wl_display_flush(connection->display);
+ wl_display_disconnect(connection->display);
+ free(connection);
+ return NULL;
+ }
+
+ wl_registry_add_listener(connection->registry,
+ ®istry_listener,
+ connection);
+ /* perform a round trip to ensure registry messages have been processed */
+ wl_display_roundtrip(connection->display);
+
+ /* all global objects from the registry should now be available. */
+
+ if (connection->shm == NULL) {
+ /* The shared memory interface is available so fail. */
+ fprintf(stderr, "No shared memory interface available\n");
+
+ free_connection(connection);
+
+ return NULL;
+ }
+
+ /* perform a round trip to ensure interface messages have been processed */
+ wl_display_roundtrip(connection->display);
+
+ /* check the XRGB8888 shared memory format is available */
+ if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
+ fprintf(stderr, "WL_SHM_FORMAT_XRGB8888 not available\n");
+
+ free_connection(connection);
+
+ return NULL;
+ }
+
+ return connection;
+}
+
+static void
+free_connection(struct wld_connection* connection)
+{
+ if (connection->compositor != NULL) {
+ wl_compositor_destroy(connection->compositor);
+ }
+
+ if (connection->shell != NULL) {
+ wl_shell_destroy(connection->shell);
+ }
+
+ if (connection->shm != NULL) {
+ wl_shm_destroy(connection->shm);
+ }
+
+ wl_registry_destroy(connection->registry);
+
+ wl_display_flush(connection->display);
+
+ wl_display_disconnect(connection->display);
+
+ free(connection);
+}
+
+typedef struct wldstate_s {
+ struct wld_connection* connection; /**< connection to wayland server */
+ struct wld_window *window;
+#if 0
+ xcb_connection_t *connection; /* The x server connection */
+ xcb_screen_t *screen; /* The screen to put the window on */
+ xcb_key_symbols_t *keysymbols; /* keysym mappings */
+
+ xcb_shm_segment_info_t shminfo;
+
+ xcb_image_t *image; /* The X image buffer */
+
+ xcb_window_t window; /* The handle to the window */
+ xcb_pixmap_t pmap; /* The handle to the backing pixmap */
+ xcb_gcontext_t gc; /* The handle to the pixmap plotting graphics context */
+ xcb_shm_seg_t segment; /* The handle to the image shared memory */
+#endif
+
+} wldstate_t;
+
+/* wayland window encompasing the display and shell surfaces */
+struct wld_window {
+ struct wld_connection* connection; /**< connection to wayland server */
+
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+ struct wl_callback *callback;
+
+ int width, height;
+
+#if 0
+ struct buffer buffers[2];
+ struct buffer *prev_buffer;
+#endif
+};
+
+static void
+handle_ping(void *data, struct wl_shell_surface *shell_surface,
+ uint32_t serial)
+{
+ wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+handle_configure(void *data, struct wl_shell_surface *shell_surface,
+ uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static void
+handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+ handle_ping,
+ handle_configure,
+ handle_popup_done
+};
+
+static struct wld_window *
+new_window(struct wld_connection *connection, int width, int height)
+{
+ struct wld_window *window;
+
+ window = calloc(1, sizeof *window);
+ if (window == NULL) {
+ return NULL;
+ }
+
+ window->connection = connection;
+ window->callback = NULL;
+ window->width = width;
+ window->height = height;
+
+ window->surface = wl_compositor_create_surface(connection->compositor);
+ if (window->surface == NULL) {
+ fprintf(stderr, "failed to create compositor surface\n");
+ free(window);
+ return NULL;
+ }
+
+ window->shell_surface = wl_shell_get_shell_surface(connection->shell,
+ window->surface);
+ if (window->shell_surface == NULL) {
+ fprintf(stderr, "failed to create shell surface\n");
+
+ wl_surface_destroy(window->surface);
+
+ free(window);
+ return NULL;
+ }
+
+ wl_shell_surface_add_listener(window->shell_surface,
+ &shell_surface_listener, window);
+
+ wl_shell_surface_set_title(window->shell_surface, "nsfb");
+
+ wl_shell_surface_set_toplevel(window->shell_surface);
+
+ return window;
+}
+
+static void
+free_window(struct wld_window *window)
+{
+ if (window->callback != NULL) {
+
+ wl_callback_destroy(window->callback);
+ }
+
+ wl_shell_surface_destroy(window->shell_surface);
+ wl_surface_destroy(window->surface);
+
+ free(window);
+}
+
+
+static int wld_initialise(nsfb_t *nsfb)
+{
+ wldstate_t *wldstate = nsfb->surface_priv;
+
+ if (wldstate != NULL)
+ return -1; /* already initialised */
+
+ /* check bpp is what we can support. */
+ if (nsfb->bpp != 32) {
+ return -1;
+ }
+
+ wldstate = calloc(1, sizeof(wldstate_t));
+ if (wldstate == NULL) {
+ return -1; /* no memory */
+ }
+
+ wldstate->connection = new_connection();
+ if (wldstate->connection == NULL) {
+ fprintf(stderr, "Error initialising wayland connection\n");
+ free(wldstate);
+ return -1; /* error */
+ }
+
+ wldstate->window = new_window(wldstate->connection,
+ nsfb->width,
+ nsfb->height);
+ if (wldstate->connection == NULL) {
+ fprintf(stderr, "Error creating wayland window\n");
+
+ free_connection(wldstate->connection);
+
+ free(wldstate);
+ return -1; /* error */
+ }
+
+ nsfb->surface_priv = wldstate;
+
+ return 0;
+}
+
+static int wld_finalise(nsfb_t *nsfb)
+{
+ wldstate_t *wldstate = nsfb->surface_priv;
+
+ if (wldstate == NULL) {
+ return 0; /* not initialised */
+ }
+
+ free_window(wldstate->window);
+
+ free_connection(wldstate->connection);
+}
+
+static int x_initialise(nsfb_t *nsfb)
+{
+ uint32_t mask;
+ uint32_t values[3];
+ xcb_size_hints_t *hints;
+ xstate_t *xstate = nsfb->surface_priv;
+ xcb_cursor_t blank_cursor;
+
+ if (xstate != NULL)
+ return -1; /* already initialised */
+
+ /* sanity check bpp. */
+ if ((nsfb->bpp != 32) && (nsfb->bpp != 16) && (nsfb->bpp != 8))
+ return -1;
+
+ xstate = calloc(1, sizeof(xstate_t));
+ if (xstate == NULL)
+ return -1; /* no memory */
+
+ /* open connection with the server */
+ xstate->connection = xcb_connect(NULL, NULL);
+ if (xstate->connection == NULL) {
+ fprintf(stderr, "Memory error opening display\n");
+ free(xstate);
+ return -1; /* no memory */
+ }
+
+ if (xcb_connection_has_error(xstate->connection) != 0) {
+ fprintf(stderr, "Error opening display\n");
+ free(xstate);
+ return -1; /* no memory */
+ }
+
+ /* get screen */
+ xstate->screen = xcb_setup_roots_iterator(xcb_get_setup(xstate->connection)).data;
+
+ /* create image */
+ xstate->image = create_shm_image(xstate, nsfb->width, nsfb->height, nsfb->bpp);
+
+ if (xstate->image == NULL)
+ xstate->image = create_image(xstate->connection, nsfb->width, nsfb->height, nsfb->bpp);
+
+ if (xstate->image == NULL) {
+ fprintf(stderr, "Unable to create image\n");
+ free(xstate);
+ xcb_disconnect(xstate->connection);
+ return -1;
+ }
+
+ /* ensure plotting information is stored */
+ nsfb->surface_priv = xstate;
+ nsfb->ptr = xstate->image->data;
+ nsfb->linelen = xstate->image->stride;
+
+ /* get blank cursor */
+ blank_cursor = create_blank_cursor(xstate->connection, xstate->screen);
+
+ /* get keysymbol maps */
+ xstate->keysymbols = xcb_key_symbols_alloc(xstate->connection);
+
+ /* create window */
+ mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
+ values[0] = xstate->screen->white_pixel;
+ values[1] = XCB_EVENT_MASK_EXPOSURE |
+ XCB_EVENT_MASK_KEY_PRESS |
+ XCB_EVENT_MASK_KEY_RELEASE |
+ XCB_EVENT_MASK_BUTTON_PRESS |
+ XCB_EVENT_MASK_BUTTON_RELEASE |
+ XCB_EVENT_MASK_POINTER_MOTION;
+ values[2] = blank_cursor;
+
+ xstate->window = xcb_generate_id(xstate->connection);
+ xcb_create_window (xstate->connection,
+ XCB_COPY_FROM_PARENT,
+ xstate->window,
+ xstate->screen->root,
+ 0, 0, xstate->image->width, xstate->image->height, 1,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ xstate->screen->root_visual,
+ mask, values);
+ /* set size hits on window */
+ hints = xcb_alloc_size_hints();
+ xcb_size_hints_set_max_size(hints, xstate->image->width, xstate->image->height);
+ xcb_size_hints_set_min_size(hints, xstate->image->width, xstate->image->height);
+ xcb_set_wm_size_hints(xstate->connection, xstate->window, WM_NORMAL_HINTS, hints);
+ xcb_free_size_hints(hints);
+
+ /* create backing pixmap */
+ xstate->pmap = xcb_generate_id(xstate->connection);
+ xcb_create_pixmap(xstate->connection, 24, xstate->pmap, xstate->window, xstate->image->width, xstate->image->height);
+
+ /* create pixmap plot gc */
+ mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
+ values[0] = xstate->screen->black_pixel;
+ values[1] = 0xffffff;
+
+ xstate->gc = xcb_generate_id (xstate->connection);
+ xcb_create_gc(xstate->connection, xstate->gc, xstate->pmap, mask, values);
+
+ /* if (nsfb->bpp == 8)
+ set_palette(nsfb);
+ */
+
+ /* put the image into the pixmap */
+ update_and_redraw_pixmap(xstate, 0, 0, xstate->image->width, xstate->image->height);
+
+
+ /* show the window */
+ xcb_map_window (xstate->connection, xstate->window);
+ xcb_flush(xstate->connection);
+
+ return 0;
+}
+
+static int x_finalise(nsfb_t *nsfb)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ if (xstate == NULL)
+ return 0;
+
+ xcb_key_symbols_free(xstate->keysymbols);
+
+ /* free pixmap */
+ xcb_free_pixmap(xstate->connection, xstate->pmap);
+
+ /* close connection to server */
+ xcb_disconnect(xstate->connection);
+
+ return 0;
+}
+
+static bool wld_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
+{
+}
+
+static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
+{
+ xcb_generic_event_t *e;
+ xcb_expose_event_t *ee;
+ xcb_motion_notify_event_t *emn;
+ xcb_button_press_event_t *ebp;
+ xcb_key_press_event_t *ekp;
+ xcb_key_press_event_t *ekr;
+ xstate_t *xstate = nsfb->surface_priv;
+
+ if (xstate == NULL)
+ return false;
+
+ xcb_flush(xstate->connection);
+
+ /* try and retrive an event immediately */
+ e = xcb_poll_for_event(xstate->connection);
+
+ if ((e == NULL) && (timeout != 0)) {
+ if (timeout > 0) {
+ int confd;
+ fd_set rfds;
+ struct timeval tv;
+ int retval;
+
+ confd = xcb_get_file_descriptor(xstate->connection);
+ FD_ZERO(&rfds);
+ FD_SET(confd, &rfds);
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = timeout % 1000;
+
+ retval = select(confd + 1, &rfds, NULL, NULL, &tv);
+ if (retval == 0) {
+ /* timeout, nothing happened */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_TIMEOUT;
+ return true;
+ }
+ }
+ e = xcb_wait_for_event(xstate->connection);
+ }
+
+ if (e == NULL) {
+ if (xcb_connection_has_error(xstate->connection) != 0) {
+ /* connection closed quiting time */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_QUIT;
+ return true;
+ } else {
+ return false; /* no event */
+ }
+ }
+
+ event->type = NSFB_EVENT_NONE;
+
+ switch (e->response_type) {
+ case XCB_EXPOSE:
+ ee = (xcb_expose_event_t *)e;
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->window,
+ xstate->gc,
+ ee->x, ee->y,
+ ee->x, ee->y,
+ ee->width, ee->height);
+ xcb_flush (xstate->connection);
+ break;
+
+ case XCB_MOTION_NOTIFY:
+ emn = (xcb_motion_notify_event_t *)e;
+ event->type = NSFB_EVENT_MOVE_ABSOLUTE;
+ event->value.vector.x = emn->event_x;
+ event->value.vector.y = emn->event_y;
+ event->value.vector.z = 0;
+ break;
+
+
+ case XCB_BUTTON_PRESS:
+ ebp = (xcb_button_press_event_t *)e;
+ event->type = NSFB_EVENT_KEY_DOWN;
+
+ switch (ebp->detail) {
+
+ case X_BUTTON_LEFT:
+ event->value.keycode = NSFB_KEY_MOUSE_1;
+ break;
+
+ case X_BUTTON_MIDDLE:
+ event->value.keycode = NSFB_KEY_MOUSE_2;
+ break;
+
+ case X_BUTTON_RIGHT:
+ event->value.keycode = NSFB_KEY_MOUSE_3;
+ break;
+
+ case X_BUTTON_WHEELUP:
+ event->value.keycode = NSFB_KEY_MOUSE_4;
+ break;
+
+ case X_BUTTON_WHEELDOWN:
+ event->value.keycode = NSFB_KEY_MOUSE_5;
+ break;
+ }
+ break;
+
+ case XCB_BUTTON_RELEASE:
+ ebp = (xcb_button_press_event_t *)e;
+ event->type = NSFB_EVENT_KEY_UP;
+
+ switch (ebp->detail) {
+
+ case X_BUTTON_LEFT:
+ event->value.keycode = NSFB_KEY_MOUSE_1;
+ break;
+
+ case X_BUTTON_MIDDLE:
+ event->value.keycode = NSFB_KEY_MOUSE_2;
+ break;
+
+ case X_BUTTON_RIGHT:
+ event->value.keycode = NSFB_KEY_MOUSE_3;
+ break;
+
+ case X_BUTTON_WHEELUP:
+ event->value.keycode = NSFB_KEY_MOUSE_4;
+ break;
+
+ case X_BUTTON_WHEELDOWN:
+ event->value.keycode = NSFB_KEY_MOUSE_5;
+ break;
+ }
+ break;
+
+
+ case XCB_KEY_PRESS:
+ ekp = (xcb_key_press_event_t *)e;
+ event->type = NSFB_EVENT_KEY_DOWN;
+ event->value.keycode = xkeysym_to_nsfbkeycode(xcb_key_symbols_get_keysym(xstate->keysymbols, ekp->detail, 0));
+ break;
+
+ case XCB_KEY_RELEASE:
+ ekr = (xcb_key_release_event_t *)e;
+ event->type = NSFB_EVENT_KEY_UP;
+ event->value.keycode = xkeysym_to_nsfbkeycode(xcb_key_symbols_get_keysym(xstate->keysymbols, ekr->detail, 0));
+ break;
+
+ }
+
+ free(e);
+
+ return true;
+}
+
+static int wld_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+}
+
+static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+ struct nsfb_cursor_s *cursor = nsfb->cursor;
+
+ if ((cursor != NULL) &&
+ (cursor->plotted == true) &&
+ (nsfb_plot_bbox_intersect(box, &cursor->loc))) {
+ nsfb_cursor_clear(nsfb, cursor);
+ }
+ return 0;
+}
+
+
+static int
+wld_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
+{
+}
+
+static int
+x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ nsfb_bbox_t redraw;
+ nsfb_bbox_t fbarea;
+
+ if ((cursor != NULL) && (cursor->plotted == true)) {
+
+ nsfb_plot_add_rect(&cursor->savloc, &cursor->loc, &redraw);
+
+ /* screen area */
+ fbarea.x0 = 0;
+ fbarea.y0 = 0;
+ fbarea.x1 = nsfb->width;
+ fbarea.y1 = nsfb->height;
+
+ nsfb_plot_clip(&fbarea, &redraw);
+
+ nsfb_cursor_clear(nsfb, cursor);
+
+ nsfb_cursor_plot(nsfb, cursor);
+
+ /* TODO: This is hediously ineficient - should keep the pointer image
+ * as a pixmap and plot server side
+ */
+ update_and_redraw_pixmap(xstate, redraw.x0, redraw.y0, redraw.x1 - redraw.x0, redraw.y1 - redraw.y0);
+
+ }
+ return true;
+}
+
+static int wld_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+}
+
+static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ struct nsfb_cursor_s *cursor = nsfb->cursor;
+
+ if ((cursor != NULL) &&
+ (cursor->plotted == false)) {
+ nsfb_cursor_plot(nsfb, cursor);
+ }
+
+ update_and_redraw_pixmap(xstate, box->x0, box->y0, box->x1 - box->x0, box->y1 - box->y0);
+
+ return 0;
+}
+
+const nsfb_surface_rtns_t wld_rtns = {
+ .initialise = wld_initialise,
+ .finalise = wld_finalise,
+ .input = wld_input,
+ .claim = wld_claim,
+ .update = wld_update,
+ .cursor = wld_cursor,
+ .geometry = wld_set_geometry,
+};
+
+NSFB_SURFACE_DEF(wld, NSFB_SURFACE_WL, &wld_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/surface/x.c b/src/surface/x.c
index b9c3429..f5ee01b 100644
--- a/src/surface/x.c
+++ b/src/surface/x.c
@@ -79,8 +79,8 @@ typedef struct xstate_s {
xcb_shm_seg_t segment; /* The handle to the image shared memory */
} xstate_t;
-/* X keyboard codepage to nsfb mapping*/
-enum nsfb_key_code_e XCSKeyboardMap[256] = {
+/* X keyboard codepage to nsfb mapping */
+static enum nsfb_key_code_e XCSKeyboardMap[256] = {
NSFB_KEY_UNKNOWN, /* */
NSFB_KEY_UNKNOWN, /* */
NSFB_KEY_UNKNOWN, /* */
diff --git a/test/runtest.sh b/test/runtest.sh
index 81739c5..464cacb 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -2,7 +2,7 @@
TEST_PATH=$1
-TEST_FRONTEND=wl
+TEST_FRONTEND=wld
${TEST_PATH}/test_frontend ${TEST_FRONTEND}
${TEST_PATH}/test_plottest ${TEST_FRONTEND}
commitdiff http://git.netsurf-browser.org/libnsfb.git/commit/?id=4b1e1482c42b31277ac...
commit 4b1e1482c42b31277acf96377013e716521982aa
Author: Vincent Sanders <vincent.sanders(a)collabora.co.uk>
Commit: Vincent Sanders <vincent.sanders(a)collabora.co.uk>
initial WIP wayland surface driver copied from x one and building
diff --git a/Makefile b/Makefile
index 8358de6..2b07e87 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ NSFB_XCB_PKG_NAMES := xcb xcb-icccm xcb-image xcb-keysyms xcb-atom
$(eval $(call pkg_config_package_available,NSFB_VNC_AVAILABLE,libvncserver))
$(eval $(call pkg_config_package_available,NSFB_SDL_AVAILABLE,sdl))
$(eval $(call pkg_config_package_available,NSFB_XCB_AVAILABLE,$(NSFB_XCB_PKG_NAMES)))
+$(eval $(call pkg_config_package_available,NSFB_WLD_AVAILABLE,wayland-client))
ifeq ($(NSFB_SDL_AVAILABLE),yes)
$(eval $(call pkg_config_package_add_flags,sdl,CFLAGS))
@@ -78,6 +79,13 @@ ifeq ($(NSFB_VNC_AVAILABLE),yes)
REQUIRED_PKGS := $(REQUIRED_PKGS) libvncserver
endif
+ifeq ($(NSFB_WLD_AVAILABLE),yes)
+ $(eval $(call pkg_config_package_add_flags,wayland-client,CFLAGS))
+ $(eval $(call pkg_config_package_add_flags,wayland-client,TESTCFLAGS,TESTLDFLAGS))
+
+ REQUIRED_PKGS := $(REQUIRED_PKGS) wayland-client
+endif
+
TESTLDFLAGS := -lm -Wl,--whole-archive -l$(COMPONENT) -Wl,--no-whole-archive $(TESTLDFLAGS)
include $(NSBUILD)/Makefile.top
diff --git a/include/libnsfb.h b/include/libnsfb.h
index da8e5f6..75d6b50 100644
--- a/include/libnsfb.h
+++ b/include/libnsfb.h
@@ -40,7 +40,8 @@ enum nsfb_type_e {
NSFB_SURFACE_LINUX, /**< Linux framebuffer surface */
NSFB_SURFACE_VNC, /**< VNC surface */
NSFB_SURFACE_ABLE, /**< ABLE framebuffer surface */
- NSFB_SURFACE_X /**< X windows surface */
+ NSFB_SURFACE_X, /**< X windows surface */
+ NSFB_SURFACE_WL /**< Wayland surface */
};
enum nsfb_format_e {
diff --git a/src/surface/Makefile b/src/surface/Makefile
index 012d9cd..332d81d 100644
--- a/src/surface/Makefile
+++ b/src/surface/Makefile
@@ -13,4 +13,8 @@ ifeq ($(NSFB_VNC_AVAILABLE),yes)
DIR_SOURCES := $(DIR_SOURCES) vnc.c
endif
+ifeq ($(NSFB_WLD_AVAILABLE),yes)
+ DIR_SOURCES := $(DIR_SOURCES) wl.c
+endif
+
include $(NSBUILD)/Makefile.subdir
diff --git a/src/surface/vnc.c b/src/surface/vnc.c
index eb32560..ca9455b 100644
--- a/src/surface/vnc.c
+++ b/src/surface/vnc.c
@@ -497,7 +497,13 @@ static bool vnc_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
event->value.controlcode = NSFB_CONTROL_TIMEOUT;
ret = rfbProcessEvents(vncscreen, timeout * 1000);
- return true;
+ if (ret == 0) {
+ /* valid event */
+ return true;
+
+ }
+
+ /* connection error occurred */
}
return false;
diff --git a/src/surface/wl.c b/src/surface/wl.c
new file mode 100644
index 0000000..fbe26cf
--- /dev/null
+++ b/src/surface/wl.c
@@ -0,0 +1,1134 @@
+/*
+ * Copyright 2009 Vincent Sanders <vince(a)simtec.co.uk>
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+#define _XOPEN_SOURCE 500
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_image.h>
+#include <xcb/xcb_atom.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/xcb_keysyms.h>
+
+#include "libnsfb.h"
+#include "libnsfb_event.h"
+#include "libnsfb_plot.h"
+#include "libnsfb_plot_util.h"
+
+#include "nsfb.h"
+#include "surface.h"
+#include "plot.h"
+#include "cursor.h"
+
+#if defined(NSFB_NEED_HINTS_ALLOC)
+static xcb_size_hints_t *
+xcb_alloc_size_hints(void)
+{
+ return calloc(1, sizeof(xcb_size_hints_t));
+}
+
+static void
+xcb_free_size_hints(xcb_size_hints_t *hints)
+{
+ free(hints);
+}
+#endif
+
+#if defined(NSFB_NEED_ICCCM_API_PREFIX)
+#define xcb_size_hints_set_max_size xcb_icccm_size_hints_set_max_size
+#define xcb_size_hints_set_min_size xcb_icccm_size_hints_set_min_size
+#define xcb_set_wm_size_hints xcb_icccm_set_wm_size_hints
+#endif
+
+#if (NSFB_XCBPROTO_MAJOR_VERSION > 1) || \
+ (NSFB_XCBPROTO_MAJOR_VERSION == 1 && NSFB_XCBPROTO_MINOR_VERSION >= 6)
+#define WM_NORMAL_HINTS XCB_ATOM_WM_NORMAL_HINTS
+#endif
+
+#define X_BUTTON_LEFT 1
+#define X_BUTTON_MIDDLE 2
+#define X_BUTTON_RIGHT 3
+#define X_BUTTON_WHEELUP 4
+#define X_BUTTON_WHEELDOWN 5
+
+typedef struct xstate_s {
+ xcb_connection_t *connection; /* The x server connection */
+ xcb_screen_t *screen; /* The screen to put the window on */
+ xcb_key_symbols_t *keysymbols; /* keysym mappings */
+
+ xcb_shm_segment_info_t shminfo;
+
+ xcb_image_t *image; /* The X image buffer */
+
+ xcb_window_t window; /* The handle to the window */
+ xcb_pixmap_t pmap; /* The handle to the backing pixmap */
+ xcb_gcontext_t gc; /* The handle to the pixmap plotting graphics context */
+ xcb_shm_seg_t segment; /* The handle to the image shared memory */
+} xstate_t;
+
+/* X keyboard codepage to nsfb mapping*/
+enum nsfb_key_code_e XCSKeyboardMap[256] = {
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_BACKSPACE, /* XK_BackSpace */
+ NSFB_KEY_TAB, /* XK_Tab */
+ NSFB_KEY_UNKNOWN, /* XK_Linefeed */
+ NSFB_KEY_CLEAR, /* XK_Clear */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_RETURN, /* XK_Return */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x10 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_PAUSE, /* XK_Pause */
+ NSFB_KEY_UNKNOWN, /* XK_Scroll_Lock */
+ NSFB_KEY_UNKNOWN, /* XK_Sys_Req */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_ESCAPE, /* XK_Escape */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x20 */
+ NSFB_KEY_UNKNOWN, /* XK_Multi_key */
+ NSFB_KEY_UNKNOWN, /* XK_Kanji */
+ NSFB_KEY_UNKNOWN, /* XK_Muhenkan */
+ NSFB_KEY_UNKNOWN, /* XK_Henkan_Mode */
+ NSFB_KEY_UNKNOWN, /* XK_Henkan */
+ NSFB_KEY_UNKNOWN, /* XK_Romaji */
+ NSFB_KEY_UNKNOWN, /* XK_Hiragana*/
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x30 */
+ NSFB_KEY_UNKNOWN, /* XK_Eisu_toggle */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_Codeinput */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_SingleCandidate */
+ NSFB_KEY_UNKNOWN, /* XK_MultipleCandidate */
+ NSFB_KEY_UNKNOWN, /* XK_PreviousCandidate */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x40 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x50 */
+ NSFB_KEY_HOME, /* XK_Home */
+ NSFB_KEY_LEFT, /* XK_Left */
+ NSFB_KEY_UP, /* XK_Up */
+ NSFB_KEY_RIGHT, /* XK_Right */
+ NSFB_KEY_DOWN, /* XK_Down */
+ NSFB_KEY_PAGEUP, /* XK_Page_Up */
+ NSFB_KEY_PAGEDOWN, /* XK_Page_Down */
+ NSFB_KEY_END, /* XK_End */
+ NSFB_KEY_UNKNOWN, /* XK_Begin */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x60 */
+ NSFB_KEY_UNKNOWN, /* XK_Select */
+ NSFB_KEY_UNKNOWN, /* XK_Print*/
+ NSFB_KEY_UNKNOWN, /* XK_Execute*/
+ NSFB_KEY_UNKNOWN, /* XK_Insert*/
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_Undo*/
+ NSFB_KEY_UNKNOWN, /* XK_Redo */
+ NSFB_KEY_UNKNOWN, /* XK_Menu */
+ NSFB_KEY_UNKNOWN, /* XK_Find */
+ NSFB_KEY_UNKNOWN, /* XK_Cancel */
+ NSFB_KEY_UNKNOWN, /* XK_Help */
+ NSFB_KEY_UNKNOWN, /* XK_Break*/
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x70 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_Mode_switch */
+ NSFB_KEY_UNKNOWN, /* XK_Num_Lock */
+ /* 0x80 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Space */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Tab */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Enter */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0x90 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_F1*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_F2*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_F3*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_F4*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Home*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Left*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Up*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Right*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Down*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Page_Up*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Page_Down*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_End*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Begin*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Insert*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Delete*/
+ /* 0xa0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Multiply*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Add*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Separator*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Subtract*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Decimal*/
+ NSFB_KEY_UNKNOWN, /* XK_KP_Divide*/
+ /* 0xb0 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_0 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_1 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_2 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_3 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_4 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_5 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_6 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_7 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_8 */
+ NSFB_KEY_UNKNOWN, /* XK_KP_9 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_F1, /* XK_F1 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* XK_KP_Equal */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_F2, /* XK_F2 */
+ /* 0xc0 */
+ NSFB_KEY_F3, /* XK_F3*/
+ NSFB_KEY_F4, /* XK_F4*/
+ NSFB_KEY_F5, /* XK_F5*/
+ NSFB_KEY_F6, /* XK_F6*/
+ NSFB_KEY_F7, /* XK_F7*/
+ NSFB_KEY_F8, /* XK_F8*/
+ NSFB_KEY_F9, /* XK_F9*/
+ NSFB_KEY_F10, /* XK_F10*/
+ NSFB_KEY_F11, /* XK_F11*/
+ NSFB_KEY_F12, /* XK_F12*/
+ NSFB_KEY_F13, /* XK_F13 */
+ NSFB_KEY_F14, /* XK_F14 */
+ NSFB_KEY_F15, /* XK_F15 */
+ NSFB_KEY_UNKNOWN, /* XK_F16 */
+ NSFB_KEY_UNKNOWN, /* XK_F17 */
+ NSFB_KEY_UNKNOWN, /* XK_F18*/
+ /* 0xd0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0xe0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_LSHIFT, /* XK_Shift_L*/
+ NSFB_KEY_RSHIFT, /* XK_Shift_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Control_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Control_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Caps_Lock*/
+ NSFB_KEY_UNKNOWN, /* XK_Shift_Lock*/
+ NSFB_KEY_UNKNOWN, /* XK_Meta_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Meta_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Alt_L */
+ NSFB_KEY_UNKNOWN, /* XK_Alt_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Super_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Super_R*/
+ NSFB_KEY_UNKNOWN, /* XK_Hyper_L*/
+ NSFB_KEY_UNKNOWN, /* XK_Hyper_R*/
+ NSFB_KEY_UNKNOWN, /* */
+ /* 0xf0 */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+ NSFB_KEY_UNKNOWN, /* */
+};
+
+/* Convert an X keysym into a nsfb key code.
+ *
+ * Our approach is primarily to assume both codings are roughly ascii like.
+ *
+ * The Keysyms are defined in X11/keysymdef.h and our mapping for the
+ * "keyboard" keys i.e. those from code set 255 is from there
+ */
+static enum nsfb_key_code_e
+xkeysym_to_nsfbkeycode(xcb_keysym_t ks)
+{
+ enum nsfb_key_code_e nsfb_key = NSFB_KEY_UNKNOWN;
+ uint8_t codeset = (ks & 0xFF00) >> 8;
+ uint8_t chrcode = ks & 0xFF;
+
+ if (ks != XCB_NO_SYMBOL) {
+
+ switch (codeset) {
+ case 0x00: /* Latin 1 */
+ case 0x01: /* Latin 2 */
+ case 0x02: /* Latin 3 */
+ case 0x03: /* Latin 4 */
+ case 0x04: /* Katakana */
+ case 0x05: /* Arabic */
+ case 0x06: /* Cyrillic */
+ case 0x07: /* Greek */
+ case 0x08: /* Technical */
+ case 0x0A: /* Publishing */
+ case 0x0C: /* Hebrew */
+ case 0x0D: /* Thai */
+ /* this is somewhat incomplete, but the nsfb codes are lined up on
+ * the ascii codes and x seems to have done similar
+ */
+ nsfb_key = (enum nsfb_key_code_e)chrcode;
+ break;
+
+ case 0xFF: /* Keyboard */
+ nsfb_key = XCSKeyboardMap[chrcode];
+ break;
+ }
+ }
+
+ return nsfb_key;
+}
+/*
+ static void
+ set_palette(nsfb_t *nsfb)
+ {
+ X_Surface *x_screen = nsfb->surface_priv;
+ X_Color palette[256];
+ int rloop, gloop, bloop;
+ int loop = 0;
+
+ // build a linear R:3 G:3 B:2 colour cube palette.
+ for (rloop = 0; rloop < 8; rloop++) {
+ for (gloop = 0; gloop < 8; gloop++) {
+ for (bloop = 0; bloop < 4; bloop++) {
+ palette[loop].r = (rloop << 5) | (rloop << 2) | (rloop >> 1);
+ palette[loop].g = (gloop << 5) | (gloop << 2) | (gloop >> 1);
+ palette[loop].b = (bloop << 6) | (bloop << 4) | (bloop << 2) | (bloop);
+ nsfb->palette[loop] = palette[loop].r |
+ palette[loop].g << 8 |
+ palette[loop].b << 16;
+ loop++;
+ }
+ }
+ }
+
+ // Set palette
+ //X_SetColors(x_screen, palette, 0, 256);
+
+ }
+*/
+static int
+update_pixmap(xstate_t *xstate, int x, int y, int width, int height)
+{
+ if (xstate->shminfo.shmseg == 0) {
+ /* not using shared memory */
+ xcb_put_image(xstate->connection,
+ xstate->image->format,
+ xstate->pmap,
+ xstate->gc,
+ xstate->image->width,
+ height,
+ 0,
+ y,
+ 0,
+ xstate->image->depth,
+ (height) * xstate->image->stride,
+ xstate->image->data + (y * xstate->image->stride));
+ } else {
+ /* shared memory */
+ xcb_image_shm_put(xstate->connection,
+ xstate->pmap,
+ xstate->gc,
+ xstate->image,
+ xstate->shminfo,
+ x,y,
+ x,y,
+ width,height,0);
+ }
+
+ return 0;
+}
+
+static int
+update_and_redraw_pixmap(xstate_t *xstate, int x, int y, int width, int height)
+{
+ update_pixmap(xstate, x, y, width, height);
+
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->window,
+ xstate->gc,
+ x, y,
+ x, y,
+ width, height);
+
+ xcb_flush(xstate->connection);
+
+ return 0;
+}
+
+
+static bool
+xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ nsfb_bbox_t allbox;
+ struct nsfb_cursor_s *cursor = nsfb->cursor;
+ uint8_t *srcptr;
+ uint8_t *dstptr;
+ int srcx = srcbox->x0;
+ int srcy = srcbox->y0;
+ int dstx = dstbox->x0;
+ int dsty = dstbox->y0;
+ int width = dstbox->x1 - dstbox->x0;
+ int height = dstbox->y1 - dstbox->y0;
+ int hloop;
+
+ nsfb_plot_add_rect(srcbox, dstbox, &allbox);
+
+ /* clear the cursor if its within the region to be altered */
+ if ((cursor != NULL) &&
+ (cursor->plotted == true) &&
+ (nsfb_plot_bbox_intersect(&allbox, &cursor->loc))) {
+
+ nsfb_cursor_clear(nsfb, cursor);
+ update_pixmap(xstate,
+ cursor->savloc.x0,
+ cursor->savloc.y0,
+ cursor->savloc.x1 - cursor->savloc.x0,
+ cursor->savloc.y1 - cursor->savloc.y0);
+
+ /* must sync here or local framebuffer and remote pixmap will not be
+ * consistant
+ */
+ xcb_aux_sync(xstate->connection);
+
+ }
+
+ /* copy the area on the server */
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->pmap,
+ xstate->gc,
+ srcbox->x0,
+ srcbox->y0,
+ dstbox->x0,
+ dstbox->y0,
+ srcbox->x1 - srcbox->x0,
+ srcbox->y1 - srcbox->y0);
+
+ /* do the copy in the local memory too */
+ srcptr = (nsfb->ptr +
+ (srcy * nsfb->linelen) +
+ ((srcx * nsfb->bpp) / 8));
+
+ dstptr = (nsfb->ptr +
+ (dsty * nsfb->linelen) +
+ ((dstx * nsfb->bpp) / 8));
+
+ if (width == nsfb->width) {
+ /* take shortcut and use memmove */
+ memmove(dstptr, srcptr, (width * height * nsfb->bpp) / 8);
+ } else {
+ if (srcy > dsty) {
+ for (hloop = height; hloop > 0; hloop--) {
+ memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
+ srcptr += nsfb->linelen;
+ dstptr += nsfb->linelen;
+ }
+ } else {
+ srcptr += height * nsfb->linelen;
+ dstptr += height * nsfb->linelen;
+ for (hloop = height; hloop > 0; hloop--) {
+ srcptr -= nsfb->linelen;
+ dstptr -= nsfb->linelen;
+ memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
+ }
+ }
+ }
+
+ if ((cursor != NULL) &&
+ (cursor->plotted == false)) {
+ nsfb_cursor_plot(nsfb, cursor);
+ }
+
+ /* update the x window */
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->window,
+ xstate->gc,
+ dstx, dsty,
+ dstx, dsty,
+ width, height);
+
+ return true;
+
+}
+
+
+static int
+x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
+{
+ if (nsfb->surface_priv != NULL)
+ return -1; /* if were already initialised fail */
+
+ nsfb->width = width;
+ nsfb->height = height;
+ nsfb->format = format;
+
+ /* select default sw plotters for format */
+ select_plotters(nsfb);
+
+ nsfb->plotter_fns->copy = xcopy;
+
+ return 0;
+}
+
+
+static xcb_format_t *
+find_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp)
+{
+ const xcb_setup_t *setup = xcb_get_setup(c);
+ xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
+ xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
+
+ for(; fmt != fmtend; ++fmt) {
+ if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) {
+ return fmt;
+ }
+ }
+ return 0;
+}
+
+static xcb_image_t *
+create_shm_image(xstate_t *xstate, int width, int height, int bpp)
+{
+ const xcb_setup_t *setup = xcb_get_setup(xstate->connection);
+ unsigned char *image_data;
+ xcb_format_t *fmt;
+ int depth = bpp;
+ uint32_t image_size;
+ int shmid;
+
+ xcb_shm_query_version_reply_t *rep;
+ xcb_shm_query_version_cookie_t ck;
+ xcb_void_cookie_t shm_attach_cookie;
+ xcb_generic_error_t *generic_error;
+
+ ck = xcb_shm_query_version(xstate->connection);
+ rep = xcb_shm_query_version_reply(xstate->connection, ck , NULL);
+ if (!rep) {
+ fprintf (stderr, "Server has no shm support.\n");
+ return NULL;
+ }
+
+ if ((rep->major_version < 1) ||
+ (rep->major_version == 1 && rep->minor_version == 0)) {
+ fprintf(stderr, "server SHM support is insufficient.\n");
+ free(rep);
+ return NULL;
+ }
+ free(rep);
+
+ if (bpp == 32)
+ depth = 24;
+
+ fmt = find_format(xstate->connection, depth, bpp);
+ if (fmt == NULL)
+ return NULL;
+
+ /* doing it this way ensures we deal with bpp smaller than 8 */
+ image_size = (bpp * width * height) >> 3;
+
+ /* get the shared memory segment */
+ shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777);
+ if (shmid == -1)
+ return NULL;
+
+ xstate->shminfo.shmid = shmid;
+
+ xstate->shminfo.shmaddr = shmat(xstate->shminfo.shmid, 0, 0);
+ image_data = xstate->shminfo.shmaddr;
+
+ xstate->shminfo.shmseg = xcb_generate_id(xstate->connection);
+ shm_attach_cookie = xcb_shm_attach_checked(xstate->connection,
+ xstate->shminfo.shmseg,
+ xstate->shminfo.shmid,
+ 0);
+ generic_error = xcb_request_check(xstate->connection, shm_attach_cookie);
+
+ /* either there is an error and the shm us no longer needed, or it now
+ * belongs to the x server - regardless release local reference to shared
+ * memory segment
+ */
+ shmctl(xstate->shminfo.shmid, IPC_RMID, 0);
+
+ if (generic_error != NULL) {
+ /* unable to attach shm */
+ xstate->shminfo.shmseg = 0;
+
+ free(generic_error);
+ return NULL;
+ }
+
+
+ return xcb_image_create(width,
+ height,
+ XCB_IMAGE_FORMAT_Z_PIXMAP,
+ fmt->scanline_pad,
+ fmt->depth,
+ fmt->bits_per_pixel,
+ 0,
+ setup->image_byte_order,
+ XCB_IMAGE_ORDER_LSB_FIRST,
+ image_data,
+ image_size,
+ image_data);
+}
+
+
+static xcb_image_t *
+create_image(xcb_connection_t *c, int width, int height, int bpp)
+{
+ const xcb_setup_t *setup = xcb_get_setup(c);
+ unsigned char *image_data;
+ xcb_format_t *fmt;
+ int depth = bpp;
+ uint32_t image_size;
+
+ if (bpp == 32)
+ depth = 24;
+
+ fmt = find_format(c, depth, bpp);
+ if (fmt == NULL)
+ return NULL;
+
+ /* doing it this way ensures we deal with bpp smaller than 8 */
+ image_size = (bpp * width * height) >> 3;
+
+ image_data = calloc(1, image_size);
+ if (image_data == NULL)
+ return NULL;
+
+ return xcb_image_create(width,
+ height,
+ XCB_IMAGE_FORMAT_Z_PIXMAP,
+ fmt->scanline_pad,
+ fmt->depth,
+ fmt->bits_per_pixel,
+ 0,
+ setup->image_byte_order,
+ XCB_IMAGE_ORDER_LSB_FIRST,
+ image_data,
+ image_size,
+ image_data);
+}
+
+/**
+ * Create a blank cursor.
+ * The empty pixmaps is leaked.
+ *
+ * @param conn xcb connection
+ * @param scr xcb XCB screen
+ */
+static xcb_cursor_t
+create_blank_cursor(xcb_connection_t *conn, const xcb_screen_t *scr)
+{
+ xcb_cursor_t cur = xcb_generate_id(conn);
+ xcb_pixmap_t pix = xcb_generate_id(conn);
+ xcb_void_cookie_t ck;
+ xcb_generic_error_t *err;
+
+ ck = xcb_create_pixmap_checked (conn, 1, pix, scr->root, 1, 1);
+ err = xcb_request_check (conn, ck);
+ if (err) {
+ fprintf (stderr, "Cannot create pixmap: %d", err->error_code);
+ free (err);
+ }
+ ck = xcb_create_cursor_checked (conn, cur, pix, pix, 0, 0, 0, 0, 0, 0, 0, 0);
+ err = xcb_request_check (conn, ck);
+ if (err) {
+ fprintf (stderr, "Cannot create cursor: %d", err->error_code);
+ free (err);
+ }
+ return cur;
+}
+
+static int wl_initialise(nsfb_t *nsfb)
+{
+}
+
+static int x_initialise(nsfb_t *nsfb)
+{
+ uint32_t mask;
+ uint32_t values[3];
+ xcb_size_hints_t *hints;
+ xstate_t *xstate = nsfb->surface_priv;
+ xcb_cursor_t blank_cursor;
+
+ if (xstate != NULL)
+ return -1; /* already initialised */
+
+ /* sanity check bpp. */
+ if ((nsfb->bpp != 32) && (nsfb->bpp != 16) && (nsfb->bpp != 8))
+ return -1;
+
+ xstate = calloc(1, sizeof(xstate_t));
+ if (xstate == NULL)
+ return -1; /* no memory */
+
+ /* open connection with the server */
+ xstate->connection = xcb_connect(NULL, NULL);
+ if (xstate->connection == NULL) {
+ fprintf(stderr, "Memory error opening display\n");
+ free(xstate);
+ return -1; /* no memory */
+ }
+
+ if (xcb_connection_has_error(xstate->connection) != 0) {
+ fprintf(stderr, "Error opening display\n");
+ free(xstate);
+ return -1; /* no memory */
+ }
+
+ /* get screen */
+ xstate->screen = xcb_setup_roots_iterator(xcb_get_setup(xstate->connection)).data;
+
+ /* create image */
+ xstate->image = create_shm_image(xstate, nsfb->width, nsfb->height, nsfb->bpp);
+
+ if (xstate->image == NULL)
+ xstate->image = create_image(xstate->connection, nsfb->width, nsfb->height, nsfb->bpp);
+
+ if (xstate->image == NULL) {
+ fprintf(stderr, "Unable to create image\n");
+ free(xstate);
+ xcb_disconnect(xstate->connection);
+ return -1;
+ }
+
+ /* ensure plotting information is stored */
+ nsfb->surface_priv = xstate;
+ nsfb->ptr = xstate->image->data;
+ nsfb->linelen = xstate->image->stride;
+
+ /* get blank cursor */
+ blank_cursor = create_blank_cursor(xstate->connection, xstate->screen);
+
+ /* get keysymbol maps */
+ xstate->keysymbols = xcb_key_symbols_alloc(xstate->connection);
+
+ /* create window */
+ mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
+ values[0] = xstate->screen->white_pixel;
+ values[1] = XCB_EVENT_MASK_EXPOSURE |
+ XCB_EVENT_MASK_KEY_PRESS |
+ XCB_EVENT_MASK_KEY_RELEASE |
+ XCB_EVENT_MASK_BUTTON_PRESS |
+ XCB_EVENT_MASK_BUTTON_RELEASE |
+ XCB_EVENT_MASK_POINTER_MOTION;
+ values[2] = blank_cursor;
+
+ xstate->window = xcb_generate_id(xstate->connection);
+ xcb_create_window (xstate->connection,
+ XCB_COPY_FROM_PARENT,
+ xstate->window,
+ xstate->screen->root,
+ 0, 0, xstate->image->width, xstate->image->height, 1,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ xstate->screen->root_visual,
+ mask, values);
+ /* set size hits on window */
+ hints = xcb_alloc_size_hints();
+ xcb_size_hints_set_max_size(hints, xstate->image->width, xstate->image->height);
+ xcb_size_hints_set_min_size(hints, xstate->image->width, xstate->image->height);
+ xcb_set_wm_size_hints(xstate->connection, xstate->window, WM_NORMAL_HINTS, hints);
+ xcb_free_size_hints(hints);
+
+ /* create backing pixmap */
+ xstate->pmap = xcb_generate_id(xstate->connection);
+ xcb_create_pixmap(xstate->connection, 24, xstate->pmap, xstate->window, xstate->image->width, xstate->image->height);
+
+ /* create pixmap plot gc */
+ mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
+ values[0] = xstate->screen->black_pixel;
+ values[1] = 0xffffff;
+
+ xstate->gc = xcb_generate_id (xstate->connection);
+ xcb_create_gc(xstate->connection, xstate->gc, xstate->pmap, mask, values);
+
+ /* if (nsfb->bpp == 8)
+ set_palette(nsfb);
+ */
+
+ /* put the image into the pixmap */
+ update_and_redraw_pixmap(xstate, 0, 0, xstate->image->width, xstate->image->height);
+
+
+ /* show the window */
+ xcb_map_window (xstate->connection, xstate->window);
+ xcb_flush(xstate->connection);
+
+ return 0;
+}
+
+static int x_finalise(nsfb_t *nsfb)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ if (xstate == NULL)
+ return 0;
+
+ xcb_key_symbols_free(xstate->keysymbols);
+
+ /* free pixmap */
+ xcb_free_pixmap(xstate->connection, xstate->pmap);
+
+ /* close connection to server */
+ xcb_disconnect(xstate->connection);
+
+ return 0;
+}
+
+static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
+{
+ xcb_generic_event_t *e;
+ xcb_expose_event_t *ee;
+ xcb_motion_notify_event_t *emn;
+ xcb_button_press_event_t *ebp;
+ xcb_key_press_event_t *ekp;
+ xcb_key_press_event_t *ekr;
+ xstate_t *xstate = nsfb->surface_priv;
+
+ if (xstate == NULL)
+ return false;
+
+ xcb_flush(xstate->connection);
+
+ /* try and retrive an event immediately */
+ e = xcb_poll_for_event(xstate->connection);
+
+ if ((e == NULL) && (timeout != 0)) {
+ if (timeout > 0) {
+ int confd;
+ fd_set rfds;
+ struct timeval tv;
+ int retval;
+
+ confd = xcb_get_file_descriptor(xstate->connection);
+ FD_ZERO(&rfds);
+ FD_SET(confd, &rfds);
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = timeout % 1000;
+
+ retval = select(confd + 1, &rfds, NULL, NULL, &tv);
+ if (retval == 0) {
+ /* timeout, nothing happened */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_TIMEOUT;
+ return true;
+ }
+ }
+ e = xcb_wait_for_event(xstate->connection);
+ }
+
+ if (e == NULL) {
+ if (xcb_connection_has_error(xstate->connection) != 0) {
+ /* connection closed quiting time */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_QUIT;
+ return true;
+ } else {
+ return false; /* no event */
+ }
+ }
+
+ event->type = NSFB_EVENT_NONE;
+
+ switch (e->response_type) {
+ case XCB_EXPOSE:
+ ee = (xcb_expose_event_t *)e;
+ xcb_copy_area(xstate->connection,
+ xstate->pmap,
+ xstate->window,
+ xstate->gc,
+ ee->x, ee->y,
+ ee->x, ee->y,
+ ee->width, ee->height);
+ xcb_flush (xstate->connection);
+ break;
+
+ case XCB_MOTION_NOTIFY:
+ emn = (xcb_motion_notify_event_t *)e;
+ event->type = NSFB_EVENT_MOVE_ABSOLUTE;
+ event->value.vector.x = emn->event_x;
+ event->value.vector.y = emn->event_y;
+ event->value.vector.z = 0;
+ break;
+
+
+ case XCB_BUTTON_PRESS:
+ ebp = (xcb_button_press_event_t *)e;
+ event->type = NSFB_EVENT_KEY_DOWN;
+
+ switch (ebp->detail) {
+
+ case X_BUTTON_LEFT:
+ event->value.keycode = NSFB_KEY_MOUSE_1;
+ break;
+
+ case X_BUTTON_MIDDLE:
+ event->value.keycode = NSFB_KEY_MOUSE_2;
+ break;
+
+ case X_BUTTON_RIGHT:
+ event->value.keycode = NSFB_KEY_MOUSE_3;
+ break;
+
+ case X_BUTTON_WHEELUP:
+ event->value.keycode = NSFB_KEY_MOUSE_4;
+ break;
+
+ case X_BUTTON_WHEELDOWN:
+ event->value.keycode = NSFB_KEY_MOUSE_5;
+ break;
+ }
+ break;
+
+ case XCB_BUTTON_RELEASE:
+ ebp = (xcb_button_press_event_t *)e;
+ event->type = NSFB_EVENT_KEY_UP;
+
+ switch (ebp->detail) {
+
+ case X_BUTTON_LEFT:
+ event->value.keycode = NSFB_KEY_MOUSE_1;
+ break;
+
+ case X_BUTTON_MIDDLE:
+ event->value.keycode = NSFB_KEY_MOUSE_2;
+ break;
+
+ case X_BUTTON_RIGHT:
+ event->value.keycode = NSFB_KEY_MOUSE_3;
+ break;
+
+ case X_BUTTON_WHEELUP:
+ event->value.keycode = NSFB_KEY_MOUSE_4;
+ break;
+
+ case X_BUTTON_WHEELDOWN:
+ event->value.keycode = NSFB_KEY_MOUSE_5;
+ break;
+ }
+ break;
+
+
+ case XCB_KEY_PRESS:
+ ekp = (xcb_key_press_event_t *)e;
+ event->type = NSFB_EVENT_KEY_DOWN;
+ event->value.keycode = xkeysym_to_nsfbkeycode(xcb_key_symbols_get_keysym(xstate->keysymbols, ekp->detail, 0));
+ break;
+
+ case XCB_KEY_RELEASE:
+ ekr = (xcb_key_release_event_t *)e;
+ event->type = NSFB_EVENT_KEY_UP;
+ event->value.keycode = xkeysym_to_nsfbkeycode(xcb_key_symbols_get_keysym(xstate->keysymbols, ekr->detail, 0));
+ break;
+
+ }
+
+ free(e);
+
+ return true;
+}
+
+static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+ struct nsfb_cursor_s *cursor = nsfb->cursor;
+
+ if ((cursor != NULL) &&
+ (cursor->plotted == true) &&
+ (nsfb_plot_bbox_intersect(box, &cursor->loc))) {
+ nsfb_cursor_clear(nsfb, cursor);
+ }
+ return 0;
+}
+
+
+
+static int
+x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ nsfb_bbox_t redraw;
+ nsfb_bbox_t fbarea;
+
+ if ((cursor != NULL) && (cursor->plotted == true)) {
+
+ nsfb_plot_add_rect(&cursor->savloc, &cursor->loc, &redraw);
+
+ /* screen area */
+ fbarea.x0 = 0;
+ fbarea.y0 = 0;
+ fbarea.x1 = nsfb->width;
+ fbarea.y1 = nsfb->height;
+
+ nsfb_plot_clip(&fbarea, &redraw);
+
+ nsfb_cursor_clear(nsfb, cursor);
+
+ nsfb_cursor_plot(nsfb, cursor);
+
+ /* TODO: This is hediously ineficient - should keep the pointer image
+ * as a pixmap and plot server side
+ */
+ update_and_redraw_pixmap(xstate, redraw.x0, redraw.y0, redraw.x1 - redraw.x0, redraw.y1 - redraw.y0);
+
+ }
+ return true;
+}
+
+
+static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+ xstate_t *xstate = nsfb->surface_priv;
+ struct nsfb_cursor_s *cursor = nsfb->cursor;
+
+ if ((cursor != NULL) &&
+ (cursor->plotted == false)) {
+ nsfb_cursor_plot(nsfb, cursor);
+ }
+
+ update_and_redraw_pixmap(xstate, box->x0, box->y0, box->x1 - box->x0, box->y1 - box->y0);
+
+ return 0;
+}
+
+const nsfb_surface_rtns_t wl_rtns = {
+ .initialise = x_initialise,
+ .finalise = x_finalise,
+ .input = x_input,
+ .claim = x_claim,
+ .update = x_update,
+ .cursor = x_cursor,
+ .geometry = x_set_geometry,
+};
+
+NSFB_SURFACE_DEF(wl, NSFB_SURFACE_WL, &wl_rtns)
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/test/runtest.sh b/test/runtest.sh
index 2f484e6..81739c5 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -2,7 +2,7 @@
TEST_PATH=$1
-TEST_FRONTEND=linux
+TEST_FRONTEND=wl
${TEST_PATH}/test_frontend ${TEST_FRONTEND}
${TEST_PATH}/test_plottest ${TEST_FRONTEND}
-----------------------------------------------------------------------
--
NetSurf Framebuffer library
9 years, 10 months
netsurf: branch master updated. d0966c9d3f372b1e70e6231b9b41c04b464410f7
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/d0966c9d3f372b1e70e62...
...commit http://git.netsurf-browser.org/netsurf.git/commit/d0966c9d3f372b1e70e6231...
...tree http://git.netsurf-browser.org/netsurf.git/tree/d0966c9d3f372b1e70e6231b9...
The branch, master has been updated
via d0966c9d3f372b1e70e6231b9b41c04b464410f7 (commit)
from 91d05fc0f1c0818214bb9fc0c3c9a8d92026905a (commit)
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=d0966c9d3f372b1e70e...
commit d0966c9d3f372b1e70e6231b9b41c04b464410f7
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Fix leaked utf16 string.
diff --git a/amiga/font.c b/amiga/font.c
index d657b36..ed47f4b 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -285,6 +285,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
if (x < tx) {
/* Beyond available width,
* so don't look further */
+ free(outf16);
return true;
}
}
@@ -294,6 +295,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
if ((x < tx) && (*char_offset != 0)) {
/* Reached available width, and a space was found;
* split there. */
+ free(outf16);
return true;
}
-----------------------------------------------------------------------
Summary of changes:
amiga/font.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/amiga/font.c b/amiga/font.c
index d657b36..ed47f4b 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -285,6 +285,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
if (x < tx) {
/* Beyond available width,
* so don't look further */
+ free(outf16);
return true;
}
}
@@ -294,6 +295,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
if ((x < tx) && (*char_offset != 0)) {
/* Reached available width, and a space was found;
* split there. */
+ free(outf16);
return true;
}
--
NetSurf Browser
9 years, 10 months
netsurf: branch master updated. 91d05fc0f1c0818214bb9fc0c3c9a8d92026905a
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/91d05fc0f1c0818214bb9...
...commit http://git.netsurf-browser.org/netsurf.git/commit/91d05fc0f1c0818214bb9fc...
...tree http://git.netsurf-browser.org/netsurf.git/tree/91d05fc0f1c0818214bb9fc0c...
The branch, master has been updated
via 91d05fc0f1c0818214bb9fc0c3c9a8d92026905a (commit)
from 918aa9d26676cf912528f33dd192dfb180e34a2b (commit)
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=91d05fc0f1c0818214b...
commit 91d05fc0f1c0818214bb9fc0c3c9a8d92026905a
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Ensure that actual_x is set when string fits inside available_width.
diff --git a/amiga/font.c b/amiga/font.c
index 458e1d0..d657b36 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -245,11 +245,9 @@ bool nsfont_split(const plot_font_style_t *fstyle,
FIXED kern = 0;
int utf16charlen = 0;
struct OutlineFont *ofont, *ufont = NULL;
- uint32 tx=0,i=0;
- size_t len;
+ uint32 tx=0;
int utf8_pos = 0;
int32 tempx = 0;
- size_t coffset = 0;
ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
if(utf8_to_enc((char *)string,"UTF-16",length,(char **)&utf16) != UTF8_CONVERT_OK) return false;
@@ -269,52 +267,47 @@ bool nsfont_split(const plot_font_style_t *fstyle,
tempx = ami_font_width_glyph(ofont, *utf16, utf16next, emwidth);
- if(tempx == 0)
- {
- if(ufont == NULL)
- {
+ if (tempx == 0) {
+ if (ufont == NULL)
ufont = ami_open_outline_font(fstyle, *utf16);
- }
- if(ufont)
- {
- tempx = ami_font_width_glyph(ufont, *utf16, utf16next, emwidth);
- }
-/*
- if(tempx == 0)
- {
- tempx = ami_font_width_glyph(ofont, 0xfffd, utf16next, emwidth);
- }
-*/
+ if (ufont)
+ tempx = ami_font_width_glyph(ufont, *utf16,
+ utf16next, emwidth);
}
- tx += tempx;
-
- if ((x < tx) && (coffset != 0)) {
- /* Reached available width, and a space has been found; split there. */
- break;
-
- } else if (*(string + utf8_pos) == ' ') {
+ /* Check whether we have a space */
+ if (*(string + utf8_pos) == ' ') {
+ /* Got a space */
*actual_x = tx;
- coffset = utf8_pos;
+ *char_offset = utf8_pos;
if (x < tx) {
- /* Out of space, so don't look further */
- break;
+ /* Beyond available width,
+ * so don't look further */
+ return true;
}
}
+
+ tx += tempx;
+
+ if ((x < tx) && (*char_offset != 0)) {
+ /* Reached available width, and a space was found;
+ * split there. */
+ return true;
+ }
+
utf16 += utf16charlen;
utf8_pos = utf8_next(string, length, utf8_pos);
}
free(outf16);
- if(coffset == 0) {
- *char_offset = length;
- *actual_x = tx;
- } else {
- *char_offset = coffset;
- }
+ /* No spaces to split at, or everything fits */
+ assert(*char_offset == 0 || x >= tx);
+
+ *char_offset = length;
+ *actual_x = tx;
return true;
}
-----------------------------------------------------------------------
Summary of changes:
amiga/font.c | 61 +++++++++++++++++++++++++--------------------------------
1 files changed, 27 insertions(+), 34 deletions(-)
diff --git a/amiga/font.c b/amiga/font.c
index 458e1d0..d657b36 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -245,11 +245,9 @@ bool nsfont_split(const plot_font_style_t *fstyle,
FIXED kern = 0;
int utf16charlen = 0;
struct OutlineFont *ofont, *ufont = NULL;
- uint32 tx=0,i=0;
- size_t len;
+ uint32 tx=0;
int utf8_pos = 0;
int32 tempx = 0;
- size_t coffset = 0;
ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
if(utf8_to_enc((char *)string,"UTF-16",length,(char **)&utf16) != UTF8_CONVERT_OK) return false;
@@ -269,52 +267,47 @@ bool nsfont_split(const plot_font_style_t *fstyle,
tempx = ami_font_width_glyph(ofont, *utf16, utf16next, emwidth);
- if(tempx == 0)
- {
- if(ufont == NULL)
- {
+ if (tempx == 0) {
+ if (ufont == NULL)
ufont = ami_open_outline_font(fstyle, *utf16);
- }
- if(ufont)
- {
- tempx = ami_font_width_glyph(ufont, *utf16, utf16next, emwidth);
- }
-/*
- if(tempx == 0)
- {
- tempx = ami_font_width_glyph(ofont, 0xfffd, utf16next, emwidth);
- }
-*/
+ if (ufont)
+ tempx = ami_font_width_glyph(ufont, *utf16,
+ utf16next, emwidth);
}
- tx += tempx;
-
- if ((x < tx) && (coffset != 0)) {
- /* Reached available width, and a space has been found; split there. */
- break;
-
- } else if (*(string + utf8_pos) == ' ') {
+ /* Check whether we have a space */
+ if (*(string + utf8_pos) == ' ') {
+ /* Got a space */
*actual_x = tx;
- coffset = utf8_pos;
+ *char_offset = utf8_pos;
if (x < tx) {
- /* Out of space, so don't look further */
- break;
+ /* Beyond available width,
+ * so don't look further */
+ return true;
}
}
+
+ tx += tempx;
+
+ if ((x < tx) && (*char_offset != 0)) {
+ /* Reached available width, and a space was found;
+ * split there. */
+ return true;
+ }
+
utf16 += utf16charlen;
utf8_pos = utf8_next(string, length, utf8_pos);
}
free(outf16);
- if(coffset == 0) {
- *char_offset = length;
- *actual_x = tx;
- } else {
- *char_offset = coffset;
- }
+ /* No spaces to split at, or everything fits */
+ assert(*char_offset == 0 || x >= tx);
+
+ *char_offset = length;
+ *actual_x = tx;
return true;
}
--
NetSurf Browser
9 years, 10 months
netsurf: branch master updated. 918aa9d26676cf912528f33dd192dfb180e34a2b
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/918aa9d26676cf912528f...
...commit http://git.netsurf-browser.org/netsurf.git/commit/918aa9d26676cf912528f33...
...tree http://git.netsurf-browser.org/netsurf.git/tree/918aa9d26676cf912528f33dd...
The branch, master has been updated
via 918aa9d26676cf912528f33dd192dfb180e34a2b (commit)
from 138d2529ef70c2615f440f67f0b9adb275de63e6 (commit)
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=918aa9d26676cf91252...
commit 918aa9d26676cf912528f33dd192dfb180e34a2b
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Fix error.
diff --git a/amiga/font.c b/amiga/font.c
index f4ef878..458e1d0 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -240,7 +240,6 @@ bool nsfont_split(const plot_font_style_t *fstyle,
int x, size_t *char_offset, int *actual_x)
{
ULONG co;
- const char *str_pos = string;
uint16 *utf16 = NULL,*outf16 = NULL;
uint16 utf16next = 0;
FIXED kern = 0;
@@ -295,7 +294,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
/* Reached available width, and a space has been found; split there. */
break;
- } else if (*(string + str_pos) == ' ') {
+ } else if (*(string + utf8_pos) == ' ') {
*actual_x = tx;
coffset = utf8_pos;
-----------------------------------------------------------------------
Summary of changes:
amiga/font.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/amiga/font.c b/amiga/font.c
index f4ef878..458e1d0 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -240,7 +240,6 @@ bool nsfont_split(const plot_font_style_t *fstyle,
int x, size_t *char_offset, int *actual_x)
{
ULONG co;
- const char *str_pos = string;
uint16 *utf16 = NULL,*outf16 = NULL;
uint16 utf16next = 0;
FIXED kern = 0;
@@ -295,7 +294,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
/* Reached available width, and a space has been found; split there. */
break;
- } else if (*(string + str_pos) == ' ') {
+ } else if (*(string + utf8_pos) == ' ') {
*actual_x = tx;
coffset = utf8_pos;
--
NetSurf Browser
9 years, 10 months
netsurf: branch master updated. 138d2529ef70c2615f440f67f0b9adb275de63e6
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/138d2529ef70c2615f440...
...commit http://git.netsurf-browser.org/netsurf.git/commit/138d2529ef70c2615f440f6...
...tree http://git.netsurf-browser.org/netsurf.git/tree/138d2529ef70c2615f440f67f...
The branch, master has been updated
via 138d2529ef70c2615f440f67f0b9adb275de63e6 (commit)
from 5d7b1f40a300763feaaa0de473e9b5b30a1b541b (commit)
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=138d2529ef70c2615f4...
commit 138d2529ef70c2615f440f67f0b9adb275de63e6
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
More meddling.
diff --git a/amiga/font.c b/amiga/font.c
index 3afab2d..f4ef878 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -248,12 +248,11 @@ bool nsfont_split(const plot_font_style_t *fstyle,
struct OutlineFont *ofont, *ufont = NULL;
uint32 tx=0,i=0;
size_t len;
- int utf8len, utf8clen = 0;
+ int utf8_pos = 0;
int32 tempx = 0;
size_t coffset = 0;
ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
- len = utf8_bounded_length(string, length);
if(utf8_to_enc((char *)string,"UTF-16",length,(char **)&utf16) != UTF8_CONVERT_OK) return false;
outf16 = utf16;
if(!(ofont = ami_open_outline_font(fstyle, 0))) return false;
@@ -261,10 +260,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
*char_offset = 0;
*actual_x = 0;
- while(utf8clen < length) {
- str_pos += utf8clen;
- utf8len = utf8_char_byte_length(str_pos);
-
+ while (utf8_pos < length) {
if ((*utf16 < 0xD800) || (0xDFFF < *utf16))
utf16charlen = 1;
else
@@ -296,12 +292,12 @@ bool nsfont_split(const plot_font_style_t *fstyle,
tx += tempx;
if ((x < tx) && (coffset != 0)) {
- /* We've run out of space, and a space has been found, split there. */
+ /* Reached available width, and a space has been found; split there. */
break;
- } else if (*str_pos == ' ') {
+ } else if (*(string + str_pos) == ' ') {
*actual_x = tx;
- coffset = utf8clen;
+ coffset = utf8_pos;
if (x < tx) {
/* Out of space, so don't look further */
@@ -309,7 +305,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
}
}
utf16 += utf16charlen;
- utf8clen += utf8len;
+ utf8_pos = utf8_next(string, length, utf8_pos);
}
free(outf16);
-----------------------------------------------------------------------
Summary of changes:
amiga/font.c | 16 ++++++----------
1 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/amiga/font.c b/amiga/font.c
index 3afab2d..f4ef878 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -248,12 +248,11 @@ bool nsfont_split(const plot_font_style_t *fstyle,
struct OutlineFont *ofont, *ufont = NULL;
uint32 tx=0,i=0;
size_t len;
- int utf8len, utf8clen = 0;
+ int utf8_pos = 0;
int32 tempx = 0;
size_t coffset = 0;
ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
- len = utf8_bounded_length(string, length);
if(utf8_to_enc((char *)string,"UTF-16",length,(char **)&utf16) != UTF8_CONVERT_OK) return false;
outf16 = utf16;
if(!(ofont = ami_open_outline_font(fstyle, 0))) return false;
@@ -261,10 +260,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
*char_offset = 0;
*actual_x = 0;
- while(utf8clen < length) {
- str_pos += utf8clen;
- utf8len = utf8_char_byte_length(str_pos);
-
+ while (utf8_pos < length) {
if ((*utf16 < 0xD800) || (0xDFFF < *utf16))
utf16charlen = 1;
else
@@ -296,12 +292,12 @@ bool nsfont_split(const plot_font_style_t *fstyle,
tx += tempx;
if ((x < tx) && (coffset != 0)) {
- /* We've run out of space, and a space has been found, split there. */
+ /* Reached available width, and a space has been found; split there. */
break;
- } else if (*str_pos == ' ') {
+ } else if (*(string + str_pos) == ' ') {
*actual_x = tx;
- coffset = utf8clen;
+ coffset = utf8_pos;
if (x < tx) {
/* Out of space, so don't look further */
@@ -309,7 +305,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
}
}
utf16 += utf16charlen;
- utf8clen += utf8len;
+ utf8_pos = utf8_next(string, length, utf8_pos);
}
free(outf16);
--
NetSurf Browser
9 years, 10 months
netsurf: branch master updated. 5d7b1f40a300763feaaa0de473e9b5b30a1b541b
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/5d7b1f40a300763feaaa0...
...commit http://git.netsurf-browser.org/netsurf.git/commit/5d7b1f40a300763feaaa0de...
...tree http://git.netsurf-browser.org/netsurf.git/tree/5d7b1f40a300763feaaa0de47...
The branch, master has been updated
via 5d7b1f40a300763feaaa0de473e9b5b30a1b541b (commit)
from 8e360ff0403523409a7c2edcea9acdf46f4b8605 (commit)
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=5d7b1f40a300763feaa...
commit 5d7b1f40a300763feaaa0de473e9b5b30a1b541b
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Another attempt.
diff --git a/amiga/font.c b/amiga/font.c
index 620d56d..3afab2d 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -240,7 +240,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
int x, size_t *char_offset, int *actual_x)
{
ULONG co;
- char *ostr = (char *)string;
+ const char *str_pos = string;
uint16 *utf16 = NULL,*outf16 = NULL;
uint16 utf16next = 0;
FIXED kern = 0;
@@ -262,7 +262,8 @@ bool nsfont_split(const plot_font_style_t *fstyle,
*actual_x = 0;
while(utf8clen < length) {
- utf8len = utf8_char_byte_length(string + utf8clen);
+ str_pos += utf8clen;
+ utf8len = utf8_char_byte_length(str_pos);
if ((*utf16 < 0xD800) || (0xDFFF < *utf16))
utf16charlen = 1;
@@ -294,13 +295,18 @@ bool nsfont_split(const plot_font_style_t *fstyle,
tx += tempx;
- if((x < tx) && (coffset != 0)) {
+ if ((x < tx) && (coffset != 0)) {
/* We've run out of space, and a space has been found, split there. */
break;
- } else if (*utf16 == 0x0020) {
+ } else if (*str_pos == ' ') {
*actual_x = tx;
coffset = utf8clen;
+
+ if (x < tx) {
+ /* Out of space, so don't look further */
+ break;
+ }
}
utf16 += utf16charlen;
utf8clen += utf8len;
-----------------------------------------------------------------------
Summary of changes:
amiga/font.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/amiga/font.c b/amiga/font.c
index 620d56d..3afab2d 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -240,7 +240,7 @@ bool nsfont_split(const plot_font_style_t *fstyle,
int x, size_t *char_offset, int *actual_x)
{
ULONG co;
- char *ostr = (char *)string;
+ const char *str_pos = string;
uint16 *utf16 = NULL,*outf16 = NULL;
uint16 utf16next = 0;
FIXED kern = 0;
@@ -262,7 +262,8 @@ bool nsfont_split(const plot_font_style_t *fstyle,
*actual_x = 0;
while(utf8clen < length) {
- utf8len = utf8_char_byte_length(string + utf8clen);
+ str_pos += utf8clen;
+ utf8len = utf8_char_byte_length(str_pos);
if ((*utf16 < 0xD800) || (0xDFFF < *utf16))
utf16charlen = 1;
@@ -294,13 +295,18 @@ bool nsfont_split(const plot_font_style_t *fstyle,
tx += tempx;
- if((x < tx) && (coffset != 0)) {
+ if ((x < tx) && (coffset != 0)) {
/* We've run out of space, and a space has been found, split there. */
break;
- } else if (*utf16 == 0x0020) {
+ } else if (*str_pos == ' ') {
*actual_x = tx;
coffset = utf8clen;
+
+ if (x < tx) {
+ /* Out of space, so don't look further */
+ break;
+ }
}
utf16 += utf16charlen;
utf8clen += utf8len;
--
NetSurf Browser
9 years, 10 months
netsurf: branch master updated. 8e360ff0403523409a7c2edcea9acdf46f4b8605
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/8e360ff0403523409a7c2...
...commit http://git.netsurf-browser.org/netsurf.git/commit/8e360ff0403523409a7c2ed...
...tree http://git.netsurf-browser.org/netsurf.git/tree/8e360ff0403523409a7c2edce...
The branch, master has been updated
via 8e360ff0403523409a7c2edcea9acdf46f4b8605 (commit)
via c568a9626b13405a53ea12c49766a4f2f67db506 (commit)
from 50efd110b8cbca87cc3c5c6065b2e498301c04c6 (commit)
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=8e360ff0403523409a7...
commit 8e360ff0403523409a7c2edcea9acdf46f4b8605
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Robust detection of scroll changes.
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 212cc5b..d23a021 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -1963,11 +1963,15 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
struct textarea_msg msg;
char utf8[6];
unsigned int caret, length, b_off, b_len;
+ int h_extent = ta->h_extent;
+ int v_extent = ta->v_extent;
int line;
int byte_delta = 0;
int x, y;
bool redraw = false;
bool readonly;
+ bool bar_x = ta->bar_x;
+ bool bar_y = ta->bar_y;
/* Word separators */
static const char *sep = " .\n";
@@ -2361,16 +2365,23 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
redraw &= ~textarea_set_caret_internal(ta, caret);
/* TODO: redraw only the bit that changed */
- if (redraw) {
- msg.ta = ta;
- msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
- msg.data.redraw.x0 = ta->border_width;
- msg.data.redraw.y0 = ta->border_width;
+ msg.ta = ta;
+ msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
+ msg.data.redraw.x0 = ta->border_width;
+ msg.data.redraw.y0 = ta->border_width;
+
+ if (bar_x != (ta->bar_x != NULL) || bar_y != (ta->bar_y != NULL) ||
+ h_extent != ta->h_extent || v_extent != ta->v_extent) {
+ /* Must redraw since scrollbars have changed */
+ msg.data.redraw.x1 = ta->vis_width - ta->border_width;
+ msg.data.redraw.y1 = ta->vis_height - ta->border_width;
+ ta->callback(ta->data, &msg);
+
+ } else if (redraw) {
msg.data.redraw.x1 = ta->vis_width - ta->border_width -
((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
msg.data.redraw.y1 = ta->vis_height - ta->border_width -
((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
-
ta->callback(ta->data, &msg);
}
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=c568a9626b13405a53e...
commit c568a9626b13405a53ea12c49766a4f2f67db506
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Avoid double redraw when edit causes scroll.
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 03f8912..212cc5b 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -300,7 +300,7 @@ static bool textarea_scroll_visible(struct textarea *ta)
*
* \param ta Text area
* \param caret_b Byte offset to caret
- * \return true iff caret placed
+ * \return true iff caret placement caused a scroll
*/
static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
{
@@ -311,7 +311,7 @@ static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
int x0, y0, x1, y1;
int width, height;
struct textarea_msg msg;
- bool scrolled;
+ bool scrolled = false;
if (caret_b != -1 && caret_b > (signed)(ta->show->len - 1))
caret_b = ta->show->len - 1;
@@ -353,8 +353,6 @@ static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
/* Finally, redraw the caret */
index = textarea_get_caret(ta);
- if (index == -1)
- return false;
/* find byte offset of caret position */
b_off = index;
@@ -442,7 +440,7 @@ static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
ta->callback(ta->data, &msg);
}
- return true;
+ return scrolled;
}
@@ -1109,7 +1107,7 @@ static size_t textarea_get_b_off_xy(struct textarea *ta, int x, int y,
* \param x X coordinate
* \param y Y coordinate
* \param visible true iff (x,y) is wrt visiable area, false for global
- * \return true on success false otherwise
+ * \return true iff caret placement caused a scroll
*/
static bool textarea_set_caret_xy(struct textarea *ta, int x, int y,
bool visible)
@@ -1640,15 +1638,17 @@ bool textarea_set_caret(struct textarea *ta, int caret)
{
int b_off;
- if (caret < 0)
- return textarea_set_caret_internal(ta, -1);
- else if (caret == 0)
- return textarea_set_caret_internal(ta, 0);
-
- b_off = utf8_bounded_byte_length(ta->show->data,
- ta->show->len - 1, caret);
+ if (caret < 0) {
+ textarea_set_caret_internal(ta, -1);
+ } else if (caret == 0) {
+ textarea_set_caret_internal(ta, 0);
+ } else {
+ b_off = utf8_bounded_byte_length(ta->show->data,
+ ta->show->len - 1, caret);
+ textarea_set_caret_internal(ta, b_off);
+ }
- return textarea_set_caret_internal(ta, b_off);
+ return true;
}
@@ -2161,7 +2161,6 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
x = ta->caret_x;
y = ta->text_y_offset_baseline + line * ta->line_height;
textarea_set_caret_xy(ta, x, y, false);
- caret = textarea_get_caret(ta);
return true;
case KEY_DOWN:
@@ -2359,7 +2358,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
return false;
}
- textarea_set_caret_internal(ta, caret);
+ redraw &= ~textarea_set_caret_internal(ta, caret);
/* TODO: redraw only the bit that changed */
if (redraw) {
-----------------------------------------------------------------------
Summary of changes:
desktop/textarea.c | 54 ++++++++++++++++++++++++++++++---------------------
1 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 03f8912..d23a021 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -300,7 +300,7 @@ static bool textarea_scroll_visible(struct textarea *ta)
*
* \param ta Text area
* \param caret_b Byte offset to caret
- * \return true iff caret placed
+ * \return true iff caret placement caused a scroll
*/
static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
{
@@ -311,7 +311,7 @@ static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
int x0, y0, x1, y1;
int width, height;
struct textarea_msg msg;
- bool scrolled;
+ bool scrolled = false;
if (caret_b != -1 && caret_b > (signed)(ta->show->len - 1))
caret_b = ta->show->len - 1;
@@ -353,8 +353,6 @@ static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
/* Finally, redraw the caret */
index = textarea_get_caret(ta);
- if (index == -1)
- return false;
/* find byte offset of caret position */
b_off = index;
@@ -442,7 +440,7 @@ static bool textarea_set_caret_internal(struct textarea *ta, int caret_b)
ta->callback(ta->data, &msg);
}
- return true;
+ return scrolled;
}
@@ -1109,7 +1107,7 @@ static size_t textarea_get_b_off_xy(struct textarea *ta, int x, int y,
* \param x X coordinate
* \param y Y coordinate
* \param visible true iff (x,y) is wrt visiable area, false for global
- * \return true on success false otherwise
+ * \return true iff caret placement caused a scroll
*/
static bool textarea_set_caret_xy(struct textarea *ta, int x, int y,
bool visible)
@@ -1640,15 +1638,17 @@ bool textarea_set_caret(struct textarea *ta, int caret)
{
int b_off;
- if (caret < 0)
- return textarea_set_caret_internal(ta, -1);
- else if (caret == 0)
- return textarea_set_caret_internal(ta, 0);
-
- b_off = utf8_bounded_byte_length(ta->show->data,
- ta->show->len - 1, caret);
+ if (caret < 0) {
+ textarea_set_caret_internal(ta, -1);
+ } else if (caret == 0) {
+ textarea_set_caret_internal(ta, 0);
+ } else {
+ b_off = utf8_bounded_byte_length(ta->show->data,
+ ta->show->len - 1, caret);
+ textarea_set_caret_internal(ta, b_off);
+ }
- return textarea_set_caret_internal(ta, b_off);
+ return true;
}
@@ -1963,11 +1963,15 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
struct textarea_msg msg;
char utf8[6];
unsigned int caret, length, b_off, b_len;
+ int h_extent = ta->h_extent;
+ int v_extent = ta->v_extent;
int line;
int byte_delta = 0;
int x, y;
bool redraw = false;
bool readonly;
+ bool bar_x = ta->bar_x;
+ bool bar_y = ta->bar_y;
/* Word separators */
static const char *sep = " .\n";
@@ -2161,7 +2165,6 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
x = ta->caret_x;
y = ta->text_y_offset_baseline + line * ta->line_height;
textarea_set_caret_xy(ta, x, y, false);
- caret = textarea_get_caret(ta);
return true;
case KEY_DOWN:
@@ -2359,19 +2362,26 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
return false;
}
- textarea_set_caret_internal(ta, caret);
+ redraw &= ~textarea_set_caret_internal(ta, caret);
/* TODO: redraw only the bit that changed */
- if (redraw) {
- msg.ta = ta;
- msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
- msg.data.redraw.x0 = ta->border_width;
- msg.data.redraw.y0 = ta->border_width;
+ msg.ta = ta;
+ msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
+ msg.data.redraw.x0 = ta->border_width;
+ msg.data.redraw.y0 = ta->border_width;
+
+ if (bar_x != (ta->bar_x != NULL) || bar_y != (ta->bar_y != NULL) ||
+ h_extent != ta->h_extent || v_extent != ta->v_extent) {
+ /* Must redraw since scrollbars have changed */
+ msg.data.redraw.x1 = ta->vis_width - ta->border_width;
+ msg.data.redraw.y1 = ta->vis_height - ta->border_width;
+ ta->callback(ta->data, &msg);
+
+ } else if (redraw) {
msg.data.redraw.x1 = ta->vis_width - ta->border_width -
((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
msg.data.redraw.y1 = ta->vis_height - ta->border_width -
((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
-
ta->callback(ta->data, &msg);
}
--
NetSurf Browser
9 years, 10 months
netsurf: branch master updated. 50efd110b8cbca87cc3c5c6065b2e498301c04c6
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/50efd110b8cbca87cc3c5...
...commit http://git.netsurf-browser.org/netsurf.git/commit/50efd110b8cbca87cc3c5c6...
...tree http://git.netsurf-browser.org/netsurf.git/tree/50efd110b8cbca87cc3c5c606...
The branch, master has been updated
via 50efd110b8cbca87cc3c5c6065b2e498301c04c6 (commit)
from 3403891f63dd8842bfac48626e3ccb569893aa21 (commit)
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=50efd110b8cbca87cc3...
commit 50efd110b8cbca87cc3c5c6065b2e498301c04c6
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Use cached line length to avoid some nsfont_width calls for selection rendering in redraw.
diff --git a/desktop/textarea.c b/desktop/textarea.c
index d3a848f..03f8912 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -1860,16 +1860,14 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
/* find clip left/right for this part of line */
left = right;
- if (b_len_part != b_len || selected) {
+ if (b_len_part != b_len) {
nsfont.font_width(&fstyle, line_text, b_end,
&right);
- right += x + ta->border_width + ta->pad_left -
- ta->scroll_x;
} else {
- right = x + ta->vis_width - ta->border_width -
- (ta->bar_y != NULL ?
- SCROLLBAR_WIDTH : 0);
+ right = ta->lines[line].width;
}
+ right += x + ta->border_width + ta->pad_left -
+ ta->scroll_x;
/* set clip rectangle for line part */
s = r;
-----------------------------------------------------------------------
Summary of changes:
desktop/textarea.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/desktop/textarea.c b/desktop/textarea.c
index d3a848f..03f8912 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -1860,16 +1860,14 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
/* find clip left/right for this part of line */
left = right;
- if (b_len_part != b_len || selected) {
+ if (b_len_part != b_len) {
nsfont.font_width(&fstyle, line_text, b_end,
&right);
- right += x + ta->border_width + ta->pad_left -
- ta->scroll_x;
} else {
- right = x + ta->vis_width - ta->border_width -
- (ta->bar_y != NULL ?
- SCROLLBAR_WIDTH : 0);
+ right = ta->lines[line].width;
}
+ right += x + ta->border_width + ta->pad_left -
+ ta->scroll_x;
/* set clip rectangle for line part */
s = r;
--
NetSurf Browser
9 years, 10 months