diff options
| author | Joakim Verona | 2011-07-12 02:34:15 +0200 |
|---|---|---|
| committer | Joakim Verona | 2011-07-12 02:34:15 +0200 |
| commit | 26b79791a30bbf4702d669d60e99ce09f2cf75b0 (patch) | |
| tree | 396c503f41c4487fd518c566931b585b425ecd02 | |
| parent | 57b7a4c05659911dd596be0791c40b8eb8158611 (diff) | |
| download | emacs-26b79791a30bbf4702d669d60e99ce09f2cf75b0.tar.gz emacs-26b79791a30bbf4702d669d60e99ce09f2cf75b0.zip | |
more configure support and cleanups. the gtk2 webkit support removed because offscreen rendering is too quirky there
| -rw-r--r-- | configure.in | 87 | ||||
| -rw-r--r-- | src/Makefile.in | 8 | ||||
| -rw-r--r-- | src/insdel.c | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 31 | ||||
| -rw-r--r-- | src/xwidget-attic.c | 87 | ||||
| -rw-r--r-- | src/xwidget.c | 174 | ||||
| -rw-r--r-- | src/xwidget.h | 1 |
7 files changed, 159 insertions, 231 deletions
diff --git a/configure.in b/configure.in index b6b11ff4946..2cf33979585 100644 --- a/configure.in +++ b/configure.in | |||
| @@ -1131,48 +1131,6 @@ AC_DEFUN([PKG_CHECK_MODULES], [ | |||
| 1131 | fi | 1131 | fi |
| 1132 | ]) | 1132 | ]) |
| 1133 | 1133 | ||
| 1134 | HAVE_XWIDGETS=no | ||
| 1135 | HAVE_WEBKIT=no | ||
| 1136 | HAVE_GOOCANVAS=no | ||
| 1137 | HAVE_CLUTTER=no | ||
| 1138 | if test "${with_xwidgets}" != "no"; then | ||
| 1139 | echo "xwidgets enabled, checking webkit, and others" | ||
| 1140 | HAVE_XWIDGETS=yes | ||
| 1141 | AC_DEFINE(HAVE_XWIDGETS, 1, [Define to 1 if you have xwidgets support.]) | ||
| 1142 | #xwidgets | ||
| 1143 | #TODO | ||
| 1144 | # - enable only if gtk/gtk3 enabled | ||
| 1145 | # - webkit, goocanvas, clutter | ||
| 1146 | # - only webkit_osr is good so remove plain webkit laterish | ||
| 1147 | |||
| 1148 | #webkit version for gtk3. | ||
| 1149 | WEBKIT_REQUIRED=1.4.0 | ||
| 1150 | WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED" | ||
| 1151 | |||
| 1152 | PKG_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) | ||
| 1153 | if test $HAVE_WEBKIT = yes; then | ||
| 1154 | AC_DEFINE(HAVE_WEBKIT, 1, [Define to 1 if you have webkit support.]) | ||
| 1155 | AC_DEFINE(HAVE_WEBKIT_OSR, 1, [Define to 1 if you have webkit_osr support.]) | ||
| 1156 | fi | ||
| 1157 | |||
| 1158 | CLUTTER_REQUIRED=1.0.0 | ||
| 1159 | CLUTTER_MODULES="clutter-gtk-1.0 >= $CLUTTER_REQUIRED" | ||
| 1160 | |||
| 1161 | PKG_CHECK_MODULES(CLUTTER, $CLUTTER_MODULES, HAVE_CLUTTER=yes, HAVE_CLUTTER=no) | ||
| 1162 | if test $HAVE_CLUTTER = yes; then | ||
| 1163 | AC_DEFINE(HAVE_CLUTTER, 1, [Define to 1 if you have clutter support.]) | ||
| 1164 | fi | ||
| 1165 | |||
| 1166 | #TODO | ||
| 1167 | GOOCANVAS_REQUIRED=1.4.0 | ||
| 1168 | GOOCANVAS_MODULES="goocanvasgtk-3.0 >= $GOOCANVAS_REQUIRED" | ||
| 1169 | |||
| 1170 | PKG_CHECK_MODULES(GOOCANVAS, $GOOCANVAS_MODULES, HAVE_GOOCANVAS=yes, HAVE_GOOCANVAS=no) | ||
| 1171 | if test $HAVE_GOOCANVAS = yes; then | ||
| 1172 | AC_DEFINE(HAVE_GOOCANVAS, 1, [Define to 1 if you have goocanvas support.]) | ||
| 1173 | fi | ||
| 1174 | |||
| 1175 | fi | ||
| 1176 | 1134 | ||
| 1177 | if test "${with_sound}" != "no"; then | 1135 | if test "${with_sound}" != "no"; then |
| 1178 | # Sound support for GNU/Linux and the free BSDs. | 1136 | # Sound support for GNU/Linux and the free BSDs. |
| @@ -1983,6 +1941,51 @@ if test "${HAVE_GTK}" = "yes"; then | |||
| 1983 | 1941 | ||
| 1984 | fi | 1942 | fi |
| 1985 | 1943 | ||
| 1944 | |||
| 1945 | HAVE_XWIDGETS=no | ||
| 1946 | HAVE_WEBKIT=no | ||
| 1947 | HAVE_GOOCANVAS=no | ||
| 1948 | HAVE_CLUTTER=no | ||
| 1949 | if test "${with_xwidgets}" != "no"; then | ||
| 1950 | echo "xwidgets enabled, checking webkit, and others" | ||
| 1951 | HAVE_XWIDGETS=yes | ||
| 1952 | AC_DEFINE(HAVE_XWIDGETS, 1, [Define to 1 if you have xwidgets support.]) | ||
| 1953 | #xwidgets | ||
| 1954 | #TODO | ||
| 1955 | # - enable only if gtk/gtk3 enabled | ||
| 1956 | # - webkit, goocanvas, clutter | ||
| 1957 | # - only webkit_osr is good so remove plain webkit laterish | ||
| 1958 | |||
| 1959 | #webkit version for gtk3. | ||
| 1960 | WEBKIT_REQUIRED=1.4.0 | ||
| 1961 | WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED" | ||
| 1962 | |||
| 1963 | PKG_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) | ||
| 1964 | if test $HAVE_WEBKIT = yes; then | ||
| 1965 | # AC_DEFINE(HAVE_WEBKIT, 1, [Define to 1 if you have webkit support.]) | ||
| 1966 | AC_DEFINE(HAVE_WEBKIT_OSR, 1, [Define to 1 if you have webkit_osr support.]) | ||
| 1967 | fi | ||
| 1968 | |||
| 1969 | CLUTTER_REQUIRED=1.0.0 | ||
| 1970 | CLUTTER_MODULES="clutter-gtk-1.0 >= $CLUTTER_REQUIRED" | ||
| 1971 | |||
| 1972 | PKG_CHECK_MODULES(CLUTTER, $CLUTTER_MODULES, HAVE_CLUTTER=yes, HAVE_CLUTTER=no) | ||
| 1973 | if test $HAVE_CLUTTER = yes; then | ||
| 1974 | AC_DEFINE(HAVE_CLUTTER, 1, [Define to 1 if you have clutter support.]) | ||
| 1975 | fi | ||
| 1976 | |||
| 1977 | #TODO | ||
| 1978 | GOOCANVAS_REQUIRED=1.4.0 | ||
| 1979 | GOOCANVAS_MODULES="goocanvasgtk-3.0 >= $GOOCANVAS_REQUIRED" | ||
| 1980 | |||
| 1981 | PKG_CHECK_MODULES(GOOCANVAS, $GOOCANVAS_MODULES, HAVE_GOOCANVAS=yes, HAVE_GOOCANVAS=no) | ||
| 1982 | if test $HAVE_GOOCANVAS = yes; then | ||
| 1983 | AC_DEFINE(HAVE_GOOCANVAS, 1, [Define to 1 if you have goocanvas support.]) | ||
| 1984 | fi | ||
| 1985 | |||
| 1986 | fi | ||
| 1987 | |||
| 1988 | |||
| 1986 | dnl D-Bus has been tested under GNU/Linux only. Must be adapted for | 1989 | dnl D-Bus has been tested under GNU/Linux only. Must be adapted for |
| 1987 | dnl other platforms. Support for higher D-Bus versions than 1.0 is | 1990 | dnl other platforms. Support for higher D-Bus versions than 1.0 is |
| 1988 | dnl also not configured. | 1991 | dnl also not configured. |
diff --git a/src/Makefile.in b/src/Makefile.in index 2d4724e5fe9..d1e212e92b7 100644 --- a/src/Makefile.in +++ b/src/Makefile.in | |||
| @@ -226,6 +226,12 @@ CFLAGS_SOUND= @CFLAGS_SOUND@ | |||
| 226 | RSVG_LIBS= @RSVG_LIBS@ | 226 | RSVG_LIBS= @RSVG_LIBS@ |
| 227 | RSVG_CFLAGS= @RSVG_CFLAGS@ | 227 | RSVG_CFLAGS= @RSVG_CFLAGS@ |
| 228 | 228 | ||
| 229 | CLUTTER_LIBS= @CLUTTER_LIBS@ | ||
| 230 | CLUTTER_CFLAGS= @CLUTTER_CFLAGS@ | ||
| 231 | |||
| 232 | WEBKIT_LIBS= @WEBKIT_LIBS@ | ||
| 233 | WEBKIT_CFLAGS= @WEBKIT_CFLAGS@ | ||
| 234 | |||
| 229 | IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ | 235 | IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ |
| 230 | IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ | 236 | IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ |
| 231 | 237 | ||
| @@ -305,6 +311,7 @@ ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I$(srcdir) \ | |||
| 305 | $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ | 311 | $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ |
| 306 | $(C_SWITCH_X_SYSTEM) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ | 312 | $(C_SWITCH_X_SYSTEM) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ |
| 307 | $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ | 313 | $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ |
| 314 | $(WEBKIT_CFLAGS) $(CLUTTER_CFLAGS) \ | ||
| 308 | $(GCONF_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ | 315 | $(GCONF_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ |
| 309 | $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) $(PROFILING_CFLAGS) \ | 316 | $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) $(PROFILING_CFLAGS) \ |
| 310 | $(LIBGNUTLS_CFLAGS) \ | 317 | $(LIBGNUTLS_CFLAGS) \ |
| @@ -382,6 +389,7 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \ | |||
| 382 | ## with GCC, we might need LIB_GCC again after them. | 389 | ## with GCC, we might need LIB_GCC again after them. |
| 383 | LIBES = $(LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \ | 390 | LIBES = $(LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \ |
| 384 | $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(DBUS_LIBS) \ | 391 | $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(DBUS_LIBS) \ |
| 392 | $(WEBKIT_LIBS) $(CLUTTER_LIBS) \ | ||
| 385 | $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ | 393 | $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ |
| 386 | $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(GCONF_LIBS) $(LIBSELINUX_LIBS) \ | 394 | $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(GCONF_LIBS) $(LIBSELINUX_LIBS) \ |
| 387 | $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ | 395 | $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ |
diff --git a/src/insdel.c b/src/insdel.c index b6639f3ad8b..dad9378c86e 100644 --- a/src/insdel.c +++ b/src/insdel.c | |||
| @@ -1797,8 +1797,6 @@ modify_region (struct buffer *buffer, EMACS_INT start, EMACS_INT end, | |||
| 1797 | int preserve_chars_modiff) | 1797 | int preserve_chars_modiff) |
| 1798 | { | 1798 | { |
| 1799 | struct buffer *old_buffer = current_buffer; | 1799 | struct buffer *old_buffer = current_buffer; |
| 1800 | // printf("modify region\n"); | ||
| 1801 | xwidget_modify_region(); | ||
| 1802 | 1800 | ||
| 1803 | if (buffer != old_buffer) | 1801 | if (buffer != old_buffer) |
| 1804 | set_buffer_internal (buffer); | 1802 | set_buffer_internal (buffer); |
diff --git a/src/xdisp.c b/src/xdisp.c index 44521ede97e..c662557845a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -22125,11 +22125,9 @@ produce_image_glyph (struct it *it) | |||
| 22125 | static void | 22125 | static void |
| 22126 | produce_xwidget_glyph (struct it *it) | 22126 | produce_xwidget_glyph (struct it *it) |
| 22127 | { | 22127 | { |
| 22128 | // struct image *img; | 22128 | struct xwidget* xw; |
| 22129 | struct face *face; | 22129 | struct face *face; |
| 22130 | int glyph_ascent, crop; | 22130 | int glyph_ascent, crop; |
| 22131 | // struct glyph_slice slice; | ||
| 22132 | |||
| 22133 | printf("produce_xwidget_glyph:\n"); | 22131 | printf("produce_xwidget_glyph:\n"); |
| 22134 | xassert (it->what == IT_XWIDGET); | 22132 | xassert (it->what == IT_XWIDGET); |
| 22135 | 22133 | ||
| @@ -22138,30 +22136,11 @@ produce_xwidget_glyph (struct it *it) | |||
| 22138 | /* Make sure X resources of the face is loaded. */ | 22136 | /* Make sure X resources of the face is loaded. */ |
| 22139 | PREPARE_FACE_FOR_DISPLAY (it->f, face); | 22137 | PREPARE_FACE_FOR_DISPLAY (it->f, face); |
| 22140 | 22138 | ||
| 22141 | ///////////////////////////////////////////// | 22139 | xw = xwidget_from_id(it->xwidget_id); |
| 22142 | 22140 | it->ascent = it->phys_ascent = glyph_ascent = xw->height/2; | |
| 22143 | // img = IMAGE_FROM_ID (it->f, it->image_id); | 22141 | it->descent = xw->height/2; |
| 22144 | //xassert (img); | ||
| 22145 | /* Make sure X resources of the image is loaded. */ | ||
| 22146 | //prepare_image_for_display (it->f, img); | ||
| 22147 | |||
| 22148 | struct xwidget* xw=xwidget_from_id(it->xwidget_id); | ||
| 22149 | //xwidget_touch(xw); | ||
| 22150 | |||
| 22151 | it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;//image_ascent (img, face, &slice); | ||
| 22152 | it->descent = xw->height/2;//slice.height - glyph_ascent; | ||
| 22153 | |||
| 22154 | //it->descent += img->vmargin; | ||
| 22155 | //it->descent += img->vmargin; | ||
| 22156 | it->phys_descent = it->descent; | 22142 | it->phys_descent = it->descent; |
| 22157 | |||
| 22158 | it->pixel_width = xw->width; | 22143 | it->pixel_width = xw->width; |
| 22159 | |||
| 22160 | //it->pixel_width += img->hmargin; | ||
| 22161 | //it->pixel_width += img->hmargin; | ||
| 22162 | |||
| 22163 | ///////////////////////////////////////// | ||
| 22164 | |||
| 22165 | /* It's quite possible for images to have an ascent greater than | 22144 | /* It's quite possible for images to have an ascent greater than |
| 22166 | their height, so don't get confused in that case. */ | 22145 | their height, so don't get confused in that case. */ |
| 22167 | if (it->descent < 0) | 22146 | if (it->descent < 0) |
| @@ -22206,7 +22185,6 @@ produce_xwidget_glyph (struct it *it) | |||
| 22206 | glyph->ascent = glyph_ascent; | 22185 | glyph->ascent = glyph_ascent; |
| 22207 | glyph->descent = it->descent; | 22186 | glyph->descent = it->descent; |
| 22208 | glyph->voffset = it->voffset; | 22187 | glyph->voffset = it->voffset; |
| 22209 | // glyph->type = IMAGE_GLYPH; | ||
| 22210 | glyph->type = XWIDGET_GLYPH; | 22188 | glyph->type = XWIDGET_GLYPH; |
| 22211 | 22189 | ||
| 22212 | glyph->multibyte_p = it->multibyte_p; | 22190 | glyph->multibyte_p = it->multibyte_p; |
| @@ -22218,7 +22196,6 @@ produce_xwidget_glyph (struct it *it) | |||
| 22218 | glyph->face_id = it->face_id; | 22196 | glyph->face_id = it->face_id; |
| 22219 | glyph->u.xwidget_id = it->xwidget_id; | 22197 | glyph->u.xwidget_id = it->xwidget_id; |
| 22220 | assert_valid_xwidget_id(glyph->u.xwidget_id,"produce_xwidget_glyph"); | 22198 | assert_valid_xwidget_id(glyph->u.xwidget_id,"produce_xwidget_glyph"); |
| 22221 | // glyph->slice = slice; | ||
| 22222 | glyph->font_type = FONT_TYPE_UNKNOWN; | 22199 | glyph->font_type = FONT_TYPE_UNKNOWN; |
| 22223 | ++it->glyph_row->used[area]; | 22200 | ++it->glyph_row->used[area]; |
| 22224 | } | 22201 | } |
diff --git a/src/xwidget-attic.c b/src/xwidget-attic.c index 84844587051..a49623124c5 100644 --- a/src/xwidget-attic.c +++ b/src/xwidget-attic.c | |||
| @@ -227,3 +227,90 @@ DEFUN ("xwidget-replug", Fxwidget_replug, Sxwidget_replug, 2, 2, 0, | |||
| 227 | 227 | ||
| 228 | return Qnil; | 228 | return Qnil; |
| 229 | } | 229 | } |
| 230 | |||
| 231 | |||
| 232 | |||
| 233 | double osr_dbg_color=0; | ||
| 234 | void webkit_osr_redraw_child ( struct xwidget* xw, GtkWidget *widget) | ||
| 235 | { | ||
| 236 | |||
| 237 | //this stuff is different in gtk3 | ||
| 238 | #ifndef HAVE_GTK3 | ||
| 239 | cairo_t *cr; | ||
| 240 | |||
| 241 | |||
| 242 | GdkPixmap *src_pixmap; | ||
| 243 | src_pixmap = gtk_offscreen_window_get_pixmap(xw->widgetwindow_osr); | ||
| 244 | |||
| 245 | //g_object_ref(src_pixmap);//TODO needs to be unrefed eventually, if we are to use his method | ||
| 246 | |||
| 247 | |||
| 248 | printf("webkit_osr_redraw_child xw.id:%d xw.type:%d window:%d\n", xw->id,xw->type, gtk_widget_get_window (widget)); | ||
| 249 | |||
| 250 | cr = gdk_cairo_create (gtk_widget_get_window (widget)); | ||
| 251 | |||
| 252 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 253 | cairo_clip(cr); | ||
| 254 | |||
| 255 | // debugging redraw: | ||
| 256 | // - the bg colors always change, so theres no error in signal handling | ||
| 257 | // - i get this error now and then: | ||
| 258 | //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11' | ||
| 259 | // seems to happen in webkit actually. see README | ||
| 260 | |||
| 261 | if(1){ //redraw debug hack | ||
| 262 | cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2); | ||
| 263 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 264 | cairo_fill(cr); | ||
| 265 | osr_dbg_color+=0.1; | ||
| 266 | if(osr_dbg_color>1.0) | ||
| 267 | osr_dbg_color=0.0; | ||
| 268 | |||
| 269 | } | ||
| 270 | |||
| 271 | gdk_cairo_set_source_pixmap (cr, src_pixmap, 0,0); //deprecated. use gdk_cairo_set_source_window | ||
| 272 | //gdk_cairo_set_source_window(cr, src_pixmap, 0,0); | ||
| 273 | |||
| 274 | cairo_set_operator (cr, CAIRO_OPERATOR_OVER); | ||
| 275 | cairo_paint_with_alpha (cr, 0.7); | ||
| 276 | //cairo_paint(cr); | ||
| 277 | |||
| 278 | |||
| 279 | cairo_destroy (cr); | ||
| 280 | #else | ||
| 281 | cairo_t *cr; | ||
| 282 | cairo_surface_t * *src_pixmap; | ||
| 283 | src_pixmap = gtk_offscreen_window_get_surface (xw->widgetwindow_osr); | ||
| 284 | |||
| 285 | printf("webkit_osr_redraw_child gtk3 xw.id:%d xw.type:%d window:%d\n", xw->id,xw->type, gtk_widget_get_window (widget)); | ||
| 286 | |||
| 287 | cr = gdk_cairo_create (gtk_widget_get_window (widget)); | ||
| 288 | |||
| 289 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 290 | cairo_clip(cr); | ||
| 291 | |||
| 292 | // debugging redraw: | ||
| 293 | // - the bg colors always change, so theres no error in signal handling | ||
| 294 | // - i get this error now and then: | ||
| 295 | //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11' | ||
| 296 | // seems to happen in webkit actually. see README | ||
| 297 | |||
| 298 | if(1){ //redraw debug hack | ||
| 299 | cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2); | ||
| 300 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 301 | cairo_fill(cr); | ||
| 302 | osr_dbg_color+=0.1; | ||
| 303 | if(osr_dbg_color>1.0) | ||
| 304 | osr_dbg_color=0.0; | ||
| 305 | |||
| 306 | } | ||
| 307 | |||
| 308 | cairo_set_source_surface (cr, src_pixmap, 0,0); | ||
| 309 | |||
| 310 | |||
| 311 | cairo_set_operator (cr, CAIRO_OPERATOR_OVER); | ||
| 312 | cairo_paint_with_alpha (cr, 0.7); | ||
| 313 | //cairo_paint(cr); | ||
| 314 | cairo_destroy (cr); | ||
| 315 | #endif | ||
| 316 | } | ||
diff --git a/src/xwidget.c b/src/xwidget.c index 6c712d1d707..ef9de279939 100644 --- a/src/xwidget.c +++ b/src/xwidget.c | |||
| @@ -89,21 +89,12 @@ | |||
| 89 | #include <clutter-gtk/clutter-gtk.h> | 89 | #include <clutter-gtk/clutter-gtk.h> |
| 90 | #endif | 90 | #endif |
| 91 | 91 | ||
| 92 | |||
| 93 | #include <wchar.h> | 92 | #include <wchar.h> |
| 94 | 93 | ||
| 95 | #ifdef HAVE_WEBKIT | ||
| 96 | #include <webkitgtk.h> | ||
| 97 | |||
| 98 | #endif | ||
| 99 | |||
| 100 | |||
| 101 | #ifdef HAVE_WEBKIT_OSR | 94 | #ifdef HAVE_WEBKIT_OSR |
| 102 | #include <webkit/webkitwebview.h> | 95 | #include <webkit/webkitwebview.h> |
| 103 | #endif | 96 | #endif |
| 104 | 97 | ||
| 105 | |||
| 106 | |||
| 107 | #include "xwidget.h" | 98 | #include "xwidget.h" |
| 108 | 99 | ||
| 109 | //TODO should of course not be a hardcoded array but I can't be bothered atm | 100 | //TODO should of course not be a hardcoded array but I can't be bothered atm |
| @@ -114,9 +105,6 @@ | |||
| 114 | struct xwidget xwidgets[MAX_XWIDGETS]; | 105 | struct xwidget xwidgets[MAX_XWIDGETS]; |
| 115 | struct xwidget_view xwidget_views[MAX_XWIDGETS]; | 106 | struct xwidget_view xwidget_views[MAX_XWIDGETS]; |
| 116 | 107 | ||
| 117 | |||
| 118 | |||
| 119 | |||
| 120 | Lisp_Object Qxwidget; | 108 | Lisp_Object Qxwidget; |
| 121 | Lisp_Object Qxwidget_id; | 109 | Lisp_Object Qxwidget_id; |
| 122 | Lisp_Object Qtitle; | 110 | Lisp_Object Qtitle; |
| @@ -126,7 +114,7 @@ Lisp_Object Qxwidget_info; | |||
| 126 | Lisp_Object Qxwidget_resize_internal; | 114 | Lisp_Object Qxwidget_resize_internal; |
| 127 | Lisp_Object Qxwidget_send_keyboard_event; | 115 | Lisp_Object Qxwidget_send_keyboard_event; |
| 128 | 116 | ||
| 129 | Lisp_Object Qbutton, Qtoggle, Qslider, Qsocket, Qcairo, Qwebkit, | 117 | Lisp_Object Qbutton, Qtoggle, Qslider, Qsocket, Qcairo, |
| 130 | Qwebkit_osr, QCplist; | 118 | Qwebkit_osr, QCplist; |
| 131 | 119 | ||
| 132 | 120 | ||
| @@ -274,100 +262,6 @@ void xwidget_slider_changed (GtkRange *range, | |||
| 274 | 262 | ||
| 275 | } | 263 | } |
| 276 | 264 | ||
| 277 | double osr_dbg_color=0; | ||
| 278 | void webkit_osr_redraw_child ( struct xwidget* xw, GtkWidget *widget) | ||
| 279 | { | ||
| 280 | |||
| 281 | //this stuff is different in gtk3 | ||
| 282 | #ifndef HAVE_GTK3 | ||
| 283 | cairo_t *cr; | ||
| 284 | |||
| 285 | |||
| 286 | GdkPixmap *src_pixmap; | ||
| 287 | src_pixmap = gtk_offscreen_window_get_pixmap(xw->widgetwindow_osr); | ||
| 288 | |||
| 289 | //g_object_ref(src_pixmap);//TODO needs to be unrefed eventually, if we are to use his method | ||
| 290 | |||
| 291 | |||
| 292 | printf("webkit_osr_redraw_child xw.id:%d xw.type:%d window:%d\n", xw->id,xw->type, gtk_widget_get_window (widget)); | ||
| 293 | |||
| 294 | cr = gdk_cairo_create (gtk_widget_get_window (widget)); | ||
| 295 | |||
| 296 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 297 | cairo_clip(cr); | ||
| 298 | |||
| 299 | // debugging redraw: | ||
| 300 | // - the bg colors always change, so theres no error in signal handling | ||
| 301 | // - i get this error now and then: | ||
| 302 | //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11' | ||
| 303 | // seems to happen in webkit actually. see README | ||
| 304 | |||
| 305 | if(1){ //redraw debug hack | ||
| 306 | cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2); | ||
| 307 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 308 | cairo_fill(cr); | ||
| 309 | osr_dbg_color+=0.1; | ||
| 310 | if(osr_dbg_color>1.0) | ||
| 311 | osr_dbg_color=0.0; | ||
| 312 | |||
| 313 | } | ||
| 314 | |||
| 315 | gdk_cairo_set_source_pixmap (cr, src_pixmap, 0,0); //deprecated. use gdk_cairo_set_source_window | ||
| 316 | //gdk_cairo_set_source_window(cr, src_pixmap, 0,0); | ||
| 317 | |||
| 318 | cairo_set_operator (cr, CAIRO_OPERATOR_OVER); | ||
| 319 | cairo_paint_with_alpha (cr, 0.7); | ||
| 320 | //cairo_paint(cr); | ||
| 321 | |||
| 322 | |||
| 323 | cairo_destroy (cr); | ||
| 324 | #elseif | ||
| 325 | cairo_t *cr; | ||
| 326 | cairo_surface_t * *src_pixmap; | ||
| 327 | src_pixmap = gtk_offscreen_window_get_surface (xw->widgetwindow_osr); | ||
| 328 | |||
| 329 | printf("webkit_osr_redraw_child gtk3 xw.id:%d xw.type:%d window:%d\n", xw->id,xw->type, gtk_widget_get_window (widget)); | ||
| 330 | |||
| 331 | cr = gdk_cairo_create (gtk_widget_get_window (widget)); | ||
| 332 | |||
| 333 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 334 | cairo_clip(cr); | ||
| 335 | |||
| 336 | // debugging redraw: | ||
| 337 | // - the bg colors always change, so theres no error in signal handling | ||
| 338 | // - i get this error now and then: | ||
| 339 | //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11' | ||
| 340 | // seems to happen in webkit actually. see README | ||
| 341 | |||
| 342 | if(1){ //redraw debug hack | ||
| 343 | cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2); | ||
| 344 | cairo_rectangle(cr, 0,0, xw->width, xw->height); | ||
| 345 | cairo_fill(cr); | ||
| 346 | osr_dbg_color+=0.1; | ||
| 347 | if(osr_dbg_color>1.0) | ||
| 348 | osr_dbg_color=0.0; | ||
| 349 | |||
| 350 | } | ||
| 351 | |||
| 352 | cairo_set_source_surface (cr, src_pixmap, 0,0); | ||
| 353 | |||
| 354 | |||
| 355 | cairo_set_operator (cr, CAIRO_OPERATOR_OVER); | ||
| 356 | cairo_paint_with_alpha (cr, 0.7); | ||
| 357 | //cairo_paint(cr); | ||
| 358 | cairo_destroy (cr); | ||
| 359 | #endif | ||
| 360 | } | ||
| 361 | |||
| 362 | /* when the on-screen webkit peer view gets exposed this signal is called. | ||
| 363 | it copies the bitmap from the off-screen webkit instance to the onscreen view*/ | ||
| 364 | gboolean webkit_osr_expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data) | ||
| 365 | { | ||
| 366 | //TODO optimize by cliping to damage region | ||
| 367 | struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); | ||
| 368 | webkit_osr_redraw_child(xw, widget); | ||
| 369 | return FALSE; | ||
| 370 | } | ||
| 371 | 265 | ||
| 372 | /* when the off-screen webkit master view changes this signal is called. | 266 | /* when the off-screen webkit master view changes this signal is called. |
| 373 | it copies the bitmap from the off-screen webkit instance */ | 267 | it copies the bitmap from the off-screen webkit instance */ |
| @@ -509,18 +403,10 @@ xwidget_init_view ( | |||
| 509 | /* Show the stage: */ | 403 | /* Show the stage: */ |
| 510 | clutter_actor_show (stage); | 404 | clutter_actor_show (stage); |
| 511 | #endif | 405 | #endif |
| 512 | |||
| 513 | } else if (EQ(xww->type, Qwebkit)) { | ||
| 514 | #ifdef HAVE_WEBKIT | ||
| 515 | xv->widget = webkit_web_view_new(); | ||
| 516 | webkit_web_view_load_uri(xv->widget, "http://www.fsf.org"); | ||
| 517 | #endif | ||
| 518 | } else if (EQ(xww->type, Qwebkit_osr)) { | 406 | } else if (EQ(xww->type, Qwebkit_osr)) { |
| 519 | #ifdef HAVE_WEBKIT_OSR | 407 | #ifdef HAVE_WEBKIT_OSR |
| 520 | xv->widget = gtk_drawing_area_new(); | 408 | xv->widget = gtk_drawing_area_new(); |
| 521 | gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling | 409 | gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling |
| 522 | #endif | ||
| 523 | #ifdef HAVE_GTK3 //and webkit_osr | ||
| 524 | gtk_widget_add_events(xv->widget, | 410 | gtk_widget_add_events(xv->widget, |
| 525 | GDK_BUTTON_PRESS_MASK | 411 | GDK_BUTTON_PRESS_MASK |
| 526 | | GDK_BUTTON_RELEASE_MASK | 412 | | GDK_BUTTON_RELEASE_MASK |
| @@ -533,9 +419,6 @@ xwidget_init_view ( | |||
| 533 | G_CALLBACK (xwidget_osr_button_callback), NULL); | 419 | G_CALLBACK (xwidget_osr_button_callback), NULL); |
| 534 | g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event", | 420 | g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event", |
| 535 | G_CALLBACK (xwidget_osr_button_callback), NULL); | 421 | G_CALLBACK (xwidget_osr_button_callback), NULL); |
| 536 | #else | ||
| 537 | g_signal_connect (G_OBJECT ( xv->widget), "expose_event", | ||
| 538 | G_CALLBACK (webkit_osr_expose_event_callback), NULL); | ||
| 539 | #endif | 422 | #endif |
| 540 | 423 | ||
| 541 | 424 | ||
| @@ -973,7 +856,6 @@ syms_of_xwidget (void) | |||
| 973 | DEFSYM (Qslider, "slider"); | 856 | DEFSYM (Qslider, "slider"); |
| 974 | DEFSYM (Qsocket, "socket"); | 857 | DEFSYM (Qsocket, "socket"); |
| 975 | DEFSYM (Qcairo, "cairo"); | 858 | DEFSYM (Qcairo, "cairo"); |
| 976 | DEFSYM (Qwebkit ,"webkit"); | ||
| 977 | DEFSYM (Qwebkit_osr ,"webkit-osr"); | 859 | DEFSYM (Qwebkit_osr ,"webkit-osr"); |
| 978 | DEFSYM (QCplist, ":plist"); | 860 | DEFSYM (QCplist, ":plist"); |
| 979 | 861 | ||
| @@ -1101,10 +983,9 @@ void gtk_window_get_position (GtkWindow *window, | |||
| 1101 | int | 983 | int |
| 1102 | lookup_xwidget (Lisp_Object spec) | 984 | lookup_xwidget (Lisp_Object spec) |
| 1103 | { | 985 | { |
| 1104 | /*when a xwidget lisp spec is found initialize the C struct that is used in the C code. | 986 | /* When a xwidget lisp spec is found initialize the C struct that is used in the C code. |
| 1105 | this is done by redisplay so values change if the spec changes. | 987 | This is done by redisplay so values change if the spec changes. |
| 1106 | so, take special care of one-shot events | 988 | So, take special care of one-shot events |
| 1107 | xwidget_init | ||
| 1108 | */ | 989 | */ |
| 1109 | int found = 0, found1 = 0, found2 = 0; | 990 | int found = 0, found1 = 0, found2 = 0; |
| 1110 | Lisp_Object value; | 991 | Lisp_Object value; |
| @@ -1112,56 +993,46 @@ lookup_xwidget (Lisp_Object spec) | |||
| 1112 | struct xwidget *xw; | 993 | struct xwidget *xw; |
| 1113 | 994 | ||
| 1114 | value = xwidget_spec_value (spec, Qxwidget_id, &found1); | 995 | value = xwidget_spec_value (spec, Qxwidget_id, &found1); |
| 1115 | id = INTEGERP (value) ? XFASTINT (value) : 0; //id 0 by default, but id must be unique so this is dumb | 996 | id = INTEGERP (value) ? XFASTINT (value) : 0; //TODO id 0 by default, but id must be unique so this is dumb |
| 1116 | 997 | ||
| 1117 | xw = &xwidgets[id]; | 998 | xw = &xwidgets[id]; |
| 1118 | xw->id=id; | 999 | xw->id=id; |
| 1119 | value = xwidget_spec_value (spec, QCtype, &found); | 1000 | value = xwidget_spec_value (spec, QCtype, &found); |
| 1120 | xw->type = SYMBOLP (value) ? value : Qbutton; //default to button | 1001 | xw->type = SYMBOLP (value) ? value : Qbutton; //default to button |
| 1121 | value = xwidget_spec_value (spec, Qtitle, &found2); | 1002 | value = xwidget_spec_value (spec, Qtitle, &found2); |
| 1122 | xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME | 1003 | xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO |
| 1123 | 1004 | ||
| 1124 | value = xwidget_spec_value (spec, QCheight, NULL); | 1005 | value = xwidget_spec_value (spec, QCheight, NULL); |
| 1125 | xw->height = INTEGERP (value) ? XFASTINT (value) : 50; //ok | 1006 | xw->height = INTEGERP (value) ? XFASTINT (value) : 50; |
| 1126 | value = xwidget_spec_value (spec, QCwidth, NULL); | 1007 | value = xwidget_spec_value (spec, QCwidth, NULL); |
| 1127 | xw->width = INTEGERP (value) ? XFASTINT (value) : 50; //ok | 1008 | xw->width = INTEGERP (value) ? XFASTINT (value) : 50; |
| 1128 | 1009 | ||
| 1129 | value = xwidget_spec_value (spec, QCplist, NULL); | 1010 | value = xwidget_spec_value (spec, QCplist, NULL); |
| 1130 | xw->plist = value; | 1011 | xw->plist = value; |
| 1131 | printf ("xwidget_id:%d type:%d found:%d %d %d title:%s (%d,%d)\n", id, | 1012 | printf ("xwidget_id:%d type:%d found:%d %d %d title:%s (%d,%d)\n", id, |
| 1132 | xw->type, found, found1, found2, xw->title, xw->height, xw->width); | 1013 | xw->type, found, found1, found2, xw->title, xw->height, xw->width); |
| 1133 | 1014 | ||
| 1134 | |||
| 1135 | assert_valid_xwidget_id (id, "lookup_xwidget"); | 1015 | assert_valid_xwidget_id (id, "lookup_xwidget"); |
| 1136 | 1016 | ||
| 1137 | #ifdef HAVE_WEBKIT_OSR | 1017 | #ifdef HAVE_WEBKIT_OSR |
| 1138 | //diy mvc. widget is rendered offscreen(or in an onscreen separate toplevel for testing), later blitted to the views | 1018 | /* DIY mvc. widget is rendered offscreen, |
| 1019 | later bitmap copied to the views. | ||
| 1020 | */ | ||
| 1139 | if (EQ(xw->type, Qwebkit_osr) && !xw->widgetwindow_osr){ | 1021 | if (EQ(xw->type, Qwebkit_osr) && !xw->widgetwindow_osr){ |
| 1140 | BLOCK_INPUT; | 1022 | BLOCK_INPUT; |
| 1141 | //xw->widgetwindow_osr = GTK_CONTAINER (gtk_window_new ( GTK_WINDOW_TOPLEVEL)); | ||
| 1142 | //xw->widgetwindow_osr = GTK_CONTAINER (gtk_dialog_new ()); | ||
| 1143 | xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ()); | 1023 | xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ()); |
| 1144 | gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height); | 1024 | gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height); |
| 1145 | //xw->widgetwindow_osr = SELECTED_FRAME()->gwfixed; | ||
| 1146 | xw->widget_osr = webkit_web_view_new(); | 1025 | xw->widget_osr = webkit_web_view_new(); |
| 1147 | //xw->widget_osr = gtk_button_new(); | ||
| 1148 | |||
| 1149 | //random debug hack | ||
| 1150 | //gtk_widget_set_double_buffered (xw->widget_osr,FALSE); | ||
| 1151 | //gtk_widget_set_double_buffered (xw->widgetwindow_osr,FALSE); | ||
| 1152 | 1026 | ||
| 1153 | gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height); | 1027 | gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height); |
| 1154 | gtk_container_add (xw->widgetwindow_osr, xw->widget_osr); | 1028 | gtk_container_add (xw->widgetwindow_osr, xw->widget_osr); |
| 1155 | //gtk_fixed_put(GTK_FIXED(xw->widgetwindow_osr), xw->widget_osr, 0, 200); | ||
| 1156 | 1029 | ||
| 1157 | gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr)); | 1030 | gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr)); |
| 1158 | 1031 | ||
| 1159 | //store some xwidget data in the gtk widgets | 1032 | /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */ |
| 1160 | g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw)); //the xwidget | 1033 | g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw)); |
| 1161 | g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw)); //the xwidget | 1034 | g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw)); |
| 1162 | |||
| 1163 | g_signal_connect (G_OBJECT ( xw->widgetwindow_osr), "damage-event", G_CALLBACK (webkit_osr_damage_event_callback), NULL); | 1035 | g_signal_connect (G_OBJECT ( xw->widgetwindow_osr), "damage-event", G_CALLBACK (webkit_osr_damage_event_callback), NULL); |
| 1164 | //g_signal_connect (G_OBJECT ( xw->widget_osr), "draw", G_CALLBACK (webkit_osr_damage_event_callback), NULL); | ||
| 1165 | 1036 | ||
| 1166 | webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org"); | 1037 | webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org"); |
| 1167 | UNBLOCK_INPUT; | 1038 | UNBLOCK_INPUT; |
| @@ -1171,13 +1042,6 @@ lookup_xwidget (Lisp_Object spec) | |||
| 1171 | return id; | 1042 | return id; |
| 1172 | } | 1043 | } |
| 1173 | 1044 | ||
| 1174 | |||
| 1175 | |||
| 1176 | |||
| 1177 | |||
| 1178 | ////////////////////////////////// | ||
| 1179 | int region_modified = 0; | ||
| 1180 | |||
| 1181 | /*set up detection of touched xwidget*/ | 1045 | /*set up detection of touched xwidget*/ |
| 1182 | void | 1046 | void |
| 1183 | xwidget_start_redisplay (void) | 1047 | xwidget_start_redisplay (void) |
| @@ -1192,7 +1056,6 @@ xwidget_start_redisplay (void) | |||
| 1192 | void | 1056 | void |
| 1193 | xwidget_touch (struct xwidget_view *xw) | 1057 | xwidget_touch (struct xwidget_view *xw) |
| 1194 | { | 1058 | { |
| 1195 | //printf("touch xwidget %d\n", xw->id); | ||
| 1196 | xw->redisplayed = 1; | 1059 | xw->redisplayed = 1; |
| 1197 | } | 1060 | } |
| 1198 | 1061 | ||
| @@ -1203,7 +1066,6 @@ xwidget_touched (struct xwidget_view *xw) | |||
| 1203 | } | 1066 | } |
| 1204 | 1067 | ||
| 1205 | /* redisplay has ended, now we should hide untouched xwidgets | 1068 | /* redisplay has ended, now we should hide untouched xwidgets |
| 1206 | |||
| 1207 | */ | 1069 | */ |
| 1208 | void | 1070 | void |
| 1209 | xwidget_end_redisplay (struct glyph_matrix *matrix) | 1071 | xwidget_end_redisplay (struct glyph_matrix *matrix) |
| @@ -1213,7 +1075,7 @@ xwidget_end_redisplay (struct glyph_matrix *matrix) | |||
| 1213 | struct xwidget *xw; | 1075 | struct xwidget *xw; |
| 1214 | int area; | 1076 | int area; |
| 1215 | 1077 | ||
| 1216 | region_modified = 0; | 1078 | |
| 1217 | xwidget_start_redisplay (); | 1079 | xwidget_start_redisplay (); |
| 1218 | //iterate desired glyph matrix of "live" window here, hide gtk widgets | 1080 | //iterate desired glyph matrix of "live" window here, hide gtk widgets |
| 1219 | //not in the desired matrix. | 1081 | //not in the desired matrix. |
| @@ -1279,10 +1141,4 @@ xwidget_end_redisplay (struct glyph_matrix *matrix) | |||
| 1279 | } | 1141 | } |
| 1280 | } | 1142 | } |
| 1281 | 1143 | ||
| 1282 | /* some type of modification was made to the buffers(unused)*/ | ||
| 1283 | void | ||
| 1284 | xwidget_modify_region (void) | ||
| 1285 | { | ||
| 1286 | region_modified = 1; | ||
| 1287 | } | ||
| 1288 | 1144 | ||
diff --git a/src/xwidget.h b/src/xwidget.h index 732dac5e7c2..b906b71c10b 100644 --- a/src/xwidget.h +++ b/src/xwidget.h | |||
| @@ -76,7 +76,6 @@ extern int xwidget_owns_kbd; | |||
| 76 | 76 | ||
| 77 | void xwidget_start_redisplay(); | 77 | void xwidget_start_redisplay(); |
| 78 | void xwidget_end_redisplay(struct glyph_matrix* matrix); | 78 | void xwidget_end_redisplay(struct glyph_matrix* matrix); |
| 79 | void xwidget_modify_region(); | ||
| 80 | 79 | ||
| 81 | void xwidget_touch (struct xwidget_view *xw); | 80 | void xwidget_touch (struct xwidget_view *xw); |
| 82 | 81 | ||