* bug#16992: Feature request @ 2014-03-11 23:19 David Englund 2014-03-12 6:26 ` Glenn Morris 2024-11-06 22:34 ` Cecilio Pardo 0 siblings, 2 replies; 16+ messages in thread From: David Englund @ 2014-03-11 23:19 UTC (permalink / raw) To: 16992 GNU Emacs cannot use background images AFAIK or anyone in #emacs at freenode.net for that matter. However, this can be done in XEmacs. Can you please add this feature to people can personalize GNU Emacs with photos as desktop background of their beloved ones when they work.? Best regards! ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: Feature request 2014-03-11 23:19 bug#16992: Feature request David Englund @ 2014-03-12 6:26 ` Glenn Morris 2020-08-04 9:50 ` Lars Ingebrigtsen 2024-11-06 22:34 ` Cecilio Pardo 1 sibling, 1 reply; 16+ messages in thread From: Glenn Morris @ 2014-03-12 6:26 UTC (permalink / raw) To: David Englund; +Cc: 16992 David Englund wrote: > GNU Emacs cannot use background images AFAIK I think there was a patch for this some years ago, but it was never integrated (?). See eg http://lists.gnu.org/archive/html/emacs-devel/2009-06/msg00485.html http://lists.gnu.org/archive/html/emacs-devel/2003-08/msg00237.html Maybe someone would like to resurrect it. PS Please use a more meaningful subject line in future. ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: Feature request 2014-03-12 6:26 ` Glenn Morris @ 2020-08-04 9:50 ` Lars Ingebrigtsen 2021-11-05 13:42 ` bug#20647: bug#16992: feature request: background images Stefan Kangas 0 siblings, 1 reply; 16+ messages in thread From: Lars Ingebrigtsen @ 2020-08-04 9:50 UTC (permalink / raw) To: Glenn Morris; +Cc: 20647, Tadashi Watanabe, 16992, David Englund Glenn Morris <rgm@gnu.org> writes: > David Englund wrote: > >> GNU Emacs cannot use background images AFAIK > > I think there was a patch for this some years ago, but it was never > integrated (?). See eg > > http://lists.gnu.org/archive/html/emacs-devel/2009-06/msg00485.html > http://lists.gnu.org/archive/html/emacs-devel/2003-08/msg00237.html > > Maybe someone would like to resurrect it. It's apparently being kept up to date: https://github.com/wachikun/emacs_bgex Unfortunately all the text surrounding it, and even the doc strings are in Japanese, so reviewing the code is difficult. I've Cc'd the author of bgex, because it would be nice to have backgrounds in Emacs windows. Tadashi -- would you be interested in integrating the code into Emacs? If that's the case, translating it into English would be a useful first step. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#20647: bug#16992: feature request: background images 2020-08-04 9:50 ` Lars Ingebrigtsen @ 2021-11-05 13:42 ` Stefan Kangas [not found] ` <CALaEO5W3+aEtwPr7bt3zNbkNw386GXpE-vkoRoojS0HqOvDQkQ@mail.gmail.com> 0 siblings, 1 reply; 16+ messages in thread From: Stefan Kangas @ 2021-11-05 13:42 UTC (permalink / raw) To: Tadashi Watanabe Cc: 20647, Glenn Morris, Tadashi Watanabe, 16992, Lars Ingebrigtsen, David Englund Hi Tadashi Watanabe, I noticed that you have recently updated your e-mail address in the bgex.el file on https://github.com/wachikun/emacs_bgex We have discussed if it would be possible to integrate the "bgex" patch into Emacs itself. We think the feature is useful. Would you be interested in that? See the previous discussion below, or here: https://debbugs.gnu.org/20647 Thanks in advance. Best regards, Stefan Kangas Lars Ingebrigtsen <larsi@gnus.org> writes: > Glenn Morris <rgm@gnu.org> writes: > >> David Englund wrote: >> >>> GNU Emacs cannot use background images AFAIK >> >> I think there was a patch for this some years ago, but it was never >> integrated (?). See eg >> >> http://lists.gnu.org/archive/html/emacs-devel/2009-06/msg00485.html >> http://lists.gnu.org/archive/html/emacs-devel/2003-08/msg00237.html >> >> Maybe someone would like to resurrect it. > > It's apparently being kept up to date: > > https://github.com/wachikun/emacs_bgex > > Unfortunately all the text surrounding it, and even the doc strings are > in Japanese, so reviewing the code is difficult. > > I've Cc'd the author of bgex, because it would be nice to have > backgrounds in Emacs windows. > > Tadashi -- would you be interested in integrating the code into Emacs? > If that's the case, translating it into English would be a useful first > step. ^ permalink raw reply [flat|nested] 16+ messages in thread
[parent not found: <CALaEO5W3+aEtwPr7bt3zNbkNw386GXpE-vkoRoojS0HqOvDQkQ@mail.gmail.com>]
* bug#20647: bug#16992: feature request: background images [not found] ` <CALaEO5W3+aEtwPr7bt3zNbkNw386GXpE-vkoRoojS0HqOvDQkQ@mail.gmail.com> @ 2021-11-15 7:08 ` Stefan Kangas 2021-11-16 11:10 ` tadashi watanabe 0 siblings, 1 reply; 16+ messages in thread From: Stefan Kangas @ 2021-11-15 7:08 UTC (permalink / raw) To: tadashi watanabe; +Cc: 20647, Glenn Morris, Tadashi Watanabe, David Englund [Please use "Reply to all" so the discussion is in the bug tracker.] Hi Tadashi Watanabe, tadashi watanabe <twacc2020@gmail.com> writes: > Hi Stefan Kangas, > > Thanks for the email. > > I'm translating the document into English and refactoring it as well. I'll > post it to GitHub soon. > > It would be nice to see it integrated into Emacs, but the code is quite > different from the standard Emacs code when I look at it after a while.. Once it is translated, we will be able to provide feedback and hopefully we should be able to fix up any issues. Please let us know when you have posted it, and thanks for working on this. Best regards, Stefan Kangas ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#20647: bug#16992: feature request: background images 2021-11-15 7:08 ` Stefan Kangas @ 2021-11-16 11:10 ` tadashi watanabe 0 siblings, 0 replies; 16+ messages in thread From: tadashi watanabe @ 2021-11-16 11:10 UTC (permalink / raw) To: Stefan Kangas; +Cc: 20647, Glenn Morris, Tadashi Watanabe, David Englund Hi Stefan Kangas, I have translated the following and pushed it to GitHub. (This is a machine translation, so there may be some strange parts) https://github.com/wachikun/emacs_bgex/blob/master/bgex.el https://github.com/wachikun/emacs_bgex/blob/master/bgex_memo_en.txt ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2014-03-11 23:19 bug#16992: Feature request David Englund 2014-03-12 6:26 ` Glenn Morris @ 2024-11-06 22:34 ` Cecilio Pardo 2024-11-07 1:43 ` Stefan Kangas 2024-11-07 6:04 ` Eli Zaretskii 1 sibling, 2 replies; 16+ messages in thread From: Cecilio Pardo @ 2024-11-06 22:34 UTC (permalink / raw) To: 16992 Hello, I have a patch almost ready to add background images for frames. It has support only for X11+cairo and MS-Windows. I would like to have it reviewed before adding more variants, if that's ok. I am planning to also draw informational UI elements into the background (with or without an image), such us fill column indicator, maybe indent lines, but again only if the implementation looks ok. ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-06 22:34 ` Cecilio Pardo @ 2024-11-07 1:43 ` Stefan Kangas 2024-11-07 6:46 ` Cecilio Pardo 2024-11-07 6:04 ` Eli Zaretskii 1 sibling, 1 reply; 16+ messages in thread From: Stefan Kangas @ 2024-11-07 1:43 UTC (permalink / raw) To: Cecilio Pardo, 16992 Cecilio Pardo <cpardo@imayhem.com> writes: > Hello, > > I have a patch almost ready to add background images for frames. It has > support only for X11+cairo and MS-Windows. I would like to have it > reviewed before adding more variants, if that's ok. > > I am planning to also draw informational UI elements into the background > (with or without an image), such us fill column indicator, maybe indent > lines, but again only if the implementation looks ok. You forgot to attach the patch, I think? ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-07 1:43 ` Stefan Kangas @ 2024-11-07 6:46 ` Cecilio Pardo 0 siblings, 0 replies; 16+ messages in thread From: Cecilio Pardo @ 2024-11-07 6:46 UTC (permalink / raw) To: Stefan Kangas, 16992 On 07/11/2024 2:43, Stefan Kangas wrote: > Cecilio Pardo <cpardo@imayhem.com> writes: > >> Hello, >> >> I have a patch almost ready to add background images for frames. It has >> support only for X11+cairo and MS-Windows. I would like to have it >> reviewed before adding more variants, if that's ok. >> >> I am planning to also draw informational UI elements into the background >> (with or without an image), such us fill column indicator, maybe indent >> lines, but again only if the implementation looks ok. > > You forgot to attach the patch, I think? It is almost(TM) ready. ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-06 22:34 ` Cecilio Pardo 2024-11-07 1:43 ` Stefan Kangas @ 2024-11-07 6:04 ` Eli Zaretskii 2024-11-08 13:59 ` Cecilio Pardo 1 sibling, 1 reply; 16+ messages in thread From: Eli Zaretskii @ 2024-11-07 6:04 UTC (permalink / raw) To: Cecilio Pardo; +Cc: 16992 > Date: Wed, 6 Nov 2024 23:34:43 +0100 > From: Cecilio Pardo <cpardo@imayhem.com> > > Hello, > > I have a patch almost ready to add background images for frames. It has > support only for X11+cairo and MS-Windows. I would like to have it > reviewed before adding more variants, if that's ok. > > I am planning to also draw informational UI elements into the background > (with or without an image), such us fill column indicator, maybe indent > lines, but again only if the implementation looks ok. Yes, it's okay to post partial changesets for review. For the second part, I think this is a very welcome and long-desired feature, so I suggest that we discuss its projected abilities and the way it will be exposed to Lisp before you finalize the implementation. There are quite a few potential features in Emacs which could be based on something like that, and are basically blocked by our current inability to do it, so IMO we should at least have a more-or-less full list of those client features before us, as a prerequisite for discussing the implementation. Thanks! ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-07 6:04 ` Eli Zaretskii @ 2024-11-08 13:59 ` Cecilio Pardo 2024-11-08 15:46 ` Eli Zaretskii 0 siblings, 1 reply; 16+ messages in thread From: Cecilio Pardo @ 2024-11-08 13:59 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16992 [-- Attachment #1: Type: text/plain, Size: 2070 bytes --] On 07/11/2024 7:04, Eli Zaretskii wrote: > Yes, it's okay to post partial changesets for review. Here is the incomplete patch that implements background images. This should build and work for x+cairo and w32 (both mingw64 and mingw.org's) It works by adding a call to complex_bkg_clear_frame_area on all functions that clear the background. These are the functions for w32 port. For the cairo port, they are parallel: w32_clear_frame_area, w32_clear_glyph_string_rect, w32_draw_stretch_glyph_string, w32font_draw I know I'm missing at least w32_draw_image_glyph_string, but works well enough for a test. To setup the backgroud image for a frame, you would do something like this: (progn (setq bkg (create-image "icons/hicolor/128x128/apps/emacs.png")) (frame-set-background-image (selected-frame) bkg 'center nil) (frame-set-background-policy (selected-frame) t)) There are new fields in the frame struct that control general activation (background_policy), and the image to use (background_image). The image can be placed in the center, or on sides or corners with 'n, 's, 'se, 'sw, etc. The background can be filled be repeating the image passing t as the last parameter of frame-set-background-image. Also, in this patch I am drawing a red line to mark the current fill-column value for each window, to show how it would work. The simple frame image code would not change much from where it is: would add offsets, and more backends, and more points on the code that may clear the background. Right now, the background is cleared normally, and then the image is painted over if the rect was cleared with the frame's background pixel. So, frames with colored background will work. I haven't tested yet with a default font that has a background different from the frame's color. Apart from the obvious overhead of drawing the image pixels, unfortunately the frame contents can't be scrolled to reuse text pixels (dispnew.c:scrolling_window). I don't think this can't be fixed without big changes. I attach a couple of screenshots to see what to expect. [-- Attachment #2: 0001-Support-for-background-images-on-frames.patch --] [-- Type: text/plain, Size: 20823 bytes --] From 13b92b39ae212081a51c67e8c3a639f13291a55c Mon Sep 17 00:00:00 2001 From: Cecilio Pardo <cpardo@imayhem.com> Date: Tue, 5 Nov 2024 23:41:30 +0100 Subject: [PATCH] Support for background images on frames. * src/dispnew.c (scrolling_window): * src/frame.c (make_frame): (Fframe_set_background_image): (Fframe_set_background_policy): (syms_of_frame): * src/frame.h (GCALIGNED_STRUCT): * src/w32font.c (w32font_draw): * src/w32term.c (w32_clear_glyph_string_rect): (w32_draw_stretch_glyph_string): (w32_need_to_draw_simple_background): (w32_clear_frame_area_complex): (w32_clear_frame_area): * src/w32term.h: * src/xterm.c (x_clear_frame_area): --- configure.ac | 2 +- src/complexbkg.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++ src/complexbkg.h | 31 ++++++ src/dispnew.c | 3 + src/frame.c | 75 +++++++++++++ src/frame.h | 10 ++ src/ftcrfont.c | 8 ++ src/w32font.c | 8 ++ src/w32term.c | 20 +++- src/xterm.c | 13 ++- src/xterm.h | 3 + 11 files changed, 439 insertions(+), 7 deletions(-) create mode 100644 src/complexbkg.c create mode 100644 src/complexbkg.h diff --git a/configure.ac b/configure.ac index 1c7545ef984..edb237f2051 100644 --- a/configure.ac +++ b/configure.ac @@ -7630,7 +7630,7 @@ AC_DEFUN AC_DEFINE([HAVE_WINDOW_SYSTEM], [1], [Define if you have a window system.]) AC_DEFINE([POLL_FOR_INPUT], [1], [Define if you poll periodically to detect C-g.]) - WINDOW_SYSTEM_OBJ="fontset.o fringe.o image.o" + WINDOW_SYSTEM_OBJ="fontset.o fringe.o image.o complexbkg.o" if test "$window_system" = "x11" || test "$REALLY_ANDROID" = "yes"; then AC_DEFINE([HAVE_TEXT_CONVERSION], [1], diff --git a/src/complexbkg.c b/src/complexbkg.c new file mode 100644 index 00000000000..c3c5679df8b --- /dev/null +++ b/src/complexbkg.c @@ -0,0 +1,273 @@ +#include "config.h" + +#if defined(HAVE_NTGUI) +# include <windows.h> +#endif + +#if defined(USE_CAIRO) +# include "xterm.h" +#endif + +#include "lisp.h" +#include "frame.h" +#include "buffer.h" +#include "complexbkg.h" + +/* +Each GUI backend must provide its own version of the functions +get_bkg_color, begin_bkg_image, draw_bkg_image, end_bkg_image and +draw_vertical_line. The functions are called from complexbkg_clear_frame_area + +- get_bkg_color: Although the background color is passed directly to + complexbkg_clear_frame_area, a backend may compute it from other + information. +- begin_bkg_image: Called once, before any attempt to draw any image. +- draw_bkg_image: Called any number of times, always between calls to + begin_bkg_image and end_bkg_image. +- end_bkg_image: Called once, after all calls to draw_bkg_image. + */ + +#if defined(HAVE_NTGUI) + +static void +get_bkg_color (struct complexbkg_platform_info *data, unsigned long *bcolor) +{ + /* Nothing to see here */ +} + +static void +begin_bkg_image (struct complexbkg_platform_info *data, struct image *img) +{ + data->compat_hdc = CreateCompatibleDC (data->hdc); + data->orig_obj = SelectObject (data->compat_hdc, img->pixmap); +} + +static void +draw_bkg_image (struct complexbkg_platform_info *data, int dest_x, int dest_y, + int width, int height, int src_x, int src_y) +{ + BitBlt (data->hdc, dest_x, dest_y, width, height, + data->compat_hdc, src_x, src_y, SRCCOPY); +} + +static void +end_bkg_image (struct complexbkg_platform_info *data) +{ + SelectObject (data->compat_hdc, data->orig_obj); + DeleteDC (data->compat_hdc); +} + +static void +draw_vertical_line (struct complexbkg_platform_info *data, + int x, int y, int height) +{ + HANDLE pen_old = SelectObject (data->hdc, + CreatePen (PS_SOLID, 1, 0x0000FF)); + MoveToEx (data->hdc, x, y, NULL); + LineTo (data->hdc, x, y + height); + DeleteObject( SelectObject (data->hdc, pen_old) ); +} + +#elif defined(USE_CAIRO) + +/* The cairo backend uses the GC for the clipping and the background color. + If may be NULL. */ + +static void +get_bkg_color (struct complexbkg_platform_info *data, unsigned long *bcolor) +{ + if (data->gc != NULL) + { + XGCValues xgcv; + XGetGCValues (FRAME_X_DISPLAY (data->frame), + data->gc, GCBackground, &xgcv); + *bcolor = xgcv.background; + } +} + +static void +begin_bkg_image (struct complexbkg_platform_info *data, struct image *img) +{ + data->img = img; +} + +static void +draw_bkg_image (struct complexbkg_platform_info *data, int dest_x, int dest_y, + int width, int height, int src_x, int src_y) +{ + x_cr_draw_image( data->frame, + data->gc == NULL ? FRAME_OUTPUT_DATA(data->frame)->normal_gc : data->gc, + data->img->cr_data, + src_x, src_y, width, height, + dest_x, dest_y, false ); +} + +static void +end_bkg_image (struct complexbkg_platform_info *data) +{ +} + +static void +draw_vertical_line (struct complexbkg_platform_info *data, + int x, int y, int height) +{ + cairo_t *cr; + cr = x_begin_cr_clip (data->frame, NULL); + cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); + cairo_move_to (cr, x, y); + cairo_line_to (cr, x, y + height); + cairo_stroke (cr); + x_end_cr_clip(data->frame); +} + +#else /* GUI type not supported. */ +#warning "complexbkg disabled: GUI type not supported." +#define DISABLE_COMPLEXBKG 1 +#endif + +#ifndef DISABLE_COMPLEXBKG +static void +get_all_live_windows (struct window *w, struct window **dest) +{ + if (WINDOW_LEAF_P (w)) + { + int i = 0; + for (; dest[i]; i++) + ; + dest[i] = w; + dest[i+1] = NULL; + } + + if (WINDOW_INTERNAL_P (w)) + for (Lisp_Object ch = w->contents; + ch != Qnil; + ch = XWINDOW (ch)->next ) + get_all_live_windows (XWINDOW (ch), dest); +} + +void +complexbkg_clear_frame_area (struct frame *f, unsigned long bcolor, + int x, int y, int width, int height, + struct complexbkg_platform_info *data) +{ + if (f->background_policy == Qnil) + return; + + get_bkg_color (data, &bcolor); + + if (f->background_image >= 0 && bcolor == FRAME_BACKGROUND_PIXEL (f)) + { + struct image *img = IMAGE_FROM_ID (f, f->background_image); + prepare_image_for_display (f, img); + + if (!img->load_failed_p) + { + begin_bkg_image (data, img); + + if (f->background_tiled) + { + int x1 = x + width, y1 = y + height; + /* Range of tiles that need painting. */ + int tx0 = x / img->width; + int tx1 = (x + width - 1) / img->width; + int ty0 = y / img->height; + int ty1 = (y + height - 1) / img->height; + + for (int tx = tx0; tx <= tx1; tx++) + for (int ty = ty0; ty <= ty1; ty++) + { + int X = tx * img->width, Y = ty * img->width; + int X1 = X + img->width, Y1 = Y + img->height; + + /* Clip the tile against the output rectangle. */ + int + c_left = (X < x) ? (x - X) : 0, + c_right = (X1 > x1) ? (X1 - x1) : 0, + c_top = (Y < y) ? (y - Y) : 0, + c_bottom = (Y1 > y1) ? (Y1 - y1) : 0; + + draw_bkg_image (data, + X + c_left, Y + c_top, + img->width - c_right - c_left, + img->height - c_bottom - c_top, + c_left, c_top ); + } + } + else + { + int src_x = x, src_y = y; + int fw = FRAME_PIXEL_WIDTH (f), fh = FRAME_PIXEL_HEIGHT (f); + + switch (f->background_gravity) + { + case 1: /* north */ + src_x -= (fw - img->width) / 2; + break; + case 2: /* south */ + src_x -= (fw - img->width) / 2; + src_y -= fh - img->height; + break; + case 3: /* east */ + src_x -= fw - img->width; + src_y -= (fh - img->height) / 2; + break; + case 4: /* west */ + src_y -= (fh - img->height) / 2; + break; + case 5: /* ne */ + src_x -= fw - img->width; + break; + case 6: /* nw */ + break; + case 7: /* se */ + src_x -= fw - img->width; + src_y -= fh - img->height; + break; + case 8: /* sw */ + src_y -= fh - img->height; + break; + case 9: /* center */ + src_x -= (fw - img->width) / 2; + src_y -= (fh - img->height) / 2; + break; + } + + draw_bkg_image (data, x, y, width, height, src_x, src_y); + } + end_bkg_image (data); + } + } + + /* Window specific complications. */ + struct window *windows[f->number_of_windows + 1]; + windows[0] = NULL; + get_all_live_windows (XWINDOW (f->root_window), windows); + + Emacs_Rectangle zone = { x, y, width, height }; + for (int i = 0; windows[i]; i++) + { + int boxx, boxy, boxwidth, boxheight; + window_box(windows[i], TEXT_AREA, &boxx, &boxy, &boxwidth, &boxheight); + Emacs_Rectangle wbox, intersect; + wbox.x = boxx; + wbox.y = boxy; + wbox.width = boxwidth; + wbox.height = boxheight; + if (!gui_intersect_rectangles( &zone, &wbox, &intersect )) + continue; + /* This window has to update the 'intersect' rectangle. */ + + Lisp_Object fill_column = BVAR (XBUFFER (WINDOW_BUFFER (windows[i])), fill_column); + if (FIXNUMP (fill_column)) + { + /* TODO: Take the buffer's face with */ + int vertical_line_x = XFIXNUM (fill_column) * FRAME_COLUMN_WIDTH(f); + + if (wbox.x + vertical_line_x >= intersect.x + && wbox.x + vertical_line_x <= intersect.x + intersect.width) + draw_vertical_line (data, wbox.x + vertical_line_x, + intersect.y, intersect.height); + } + } +} +#endif /* DISABLE_COMPLEXBKG */ diff --git a/src/complexbkg.h b/src/complexbkg.h new file mode 100644 index 00000000000..e45ebb2edff --- /dev/null +++ b/src/complexbkg.h @@ -0,0 +1,31 @@ +#if defined(HAVE_NTGUI) + +struct complexbkg_platform_info { + HDC hdc; + /* Internal from here */ + HDC compat_hdc; + HGDIOBJ orig_obj; +}; + +#elif defined(USE_CAIRO) + +struct complexbkg_platform_info { + struct frame *frame; + GC gc; + /* Internal from here */ + struct image *img; +}; + +#else + +struct complexbkg_platform_info { + int dummy; +}; + +#endif + +void complexbkg_clear_frame_area (struct frame *f, + unsigned long bcolor, + int x, int y, + int width, int height, + struct complexbkg_platform_info *data); diff --git a/src/dispnew.c b/src/dispnew.c index 1a243079e46..ca564cd0c46 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -4549,6 +4549,9 @@ scrolling_window (struct window *w, int tab_line_p) struct row_entry *entry; struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); + if (XFRAME (WINDOW_FRAME (w))->background_policy != Qnil) + return 0; + /* Skip over rows equal at the start. */ for (i = tab_line_p; i < current_matrix->nrows - 1; ++i) { diff --git a/src/frame.c b/src/frame.c index 7f4bf274ad9..d2ff749f49d 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1009,6 +1009,11 @@ make_frame (bool mini_p) f->conversion.actions = NULL; #endif +#ifdef HAVE_WINDOW_SYSTEM + f->background_policy = Qnil; + f->background_image = -1; +#endif /* HAVE_WINDOW_SYSTEM */ + root_window = make_window (); rw = XWINDOW (root_window); if (mini_p) @@ -1696,6 +1701,64 @@ DEFUN ("frame-list", Fframe_list, Sframe_list, #endif /* HAVE_WINDOW_SYSTEM */ } +DEFUN("frame-set-background-image", Fframe_set_background_image, + Sframe_set_background_image, 2, 4, 0, + doc: /* Set the background image of FRAME to IMAGE. If present, +GRAVITY must one of symbols: n, s, e, w, ne, nw, se, sw, center. If +TILED it t, repeat the image to fill the whole frame, excetp if GRAVITY +is center. */ ) + (Lisp_Object frame, Lisp_Object image_spec, Lisp_Object gravity, Lisp_Object tiled) +{ + struct frame *f = decode_live_frame (frame); + if (NILP (image_spec)) + f->background_image = -1; + else + { + ptrdiff_t image_id = lookup_image (f, image_spec, DEFAULT_FACE_ID); + f->background_image = image_id; + } + + f->background_gravity = 6; /* north west */ + if (gravity == Qn) + f->background_gravity = 1; + else if (gravity == Qs) + f->background_gravity = 2; + else if (gravity == Qe) + f->background_gravity = 3; + else if (gravity == Qw) + f->background_gravity = 4; + else if (gravity == Qne) + f->background_gravity = 5; + else if (gravity == Qnw) + f->background_gravity = 6; + else if (gravity == Qse) + f->background_gravity = 7; + else if (gravity == Qsw) + f->background_gravity = 8; + else if (gravity == Qcenter) + f->background_gravity = 9; + + f->background_tiled = true; + if (tiled == Qnil) + f->background_tiled = false; + + SET_FRAME_GARBAGED (f); + return image_spec; +} + +DEFUN("frame-set-background-policy", Fframe_set_background_policy, + Sframe_set_background_policy, 2, 2, 0, + doc: /* Set the background policy for FRAME. */ ) + (Lisp_Object frame, Lisp_Object bp) +{ + struct frame *f = decode_live_frame (frame); + + f->background_policy = bp; + SET_FRAME_GARBAGED (f); + + return bp; +} + DEFUN ("frame-parent", Fframe_parent, Sframe_parent, 0, 1, 0, doc: /* Return the parent frame of FRAME. @@ -6817,6 +6880,8 @@ focus (where a frame immediately loses focus when it's left by the mouse frame_internal_parameters = list3 (Qname, Qparent_id, Qwindow_id); #endif + defsubr (&Sframe_set_background_image); + defsubr (&Sframe_set_background_policy); defsubr (&Sframep); defsubr (&Sframe_live_p); defsubr (&Swindow_system); @@ -6901,5 +6966,15 @@ focus (where a frame immediately loses focus when it's left by the mouse #if !defined HAVE_EXT_TOOL_BAR || defined USE_GTK Fprovide (Qmove_toolbar, Qnil); #endif /* !HAVE_EXT_TOOL_BAR || USE_GTK */ + + DEFSYM (Qn, "n"); + DEFSYM (Qs, "s"); + DEFSYM (Qe, "e"); + DEFSYM (Qw, "w"); + DEFSYM (Qne, "ne"); + DEFSYM (Qnw, "nw"); + DEFSYM (Qse, "se"); + DEFSYM (Qsw, "sw"); + DEFSYM (Qcenter, "center"); #endif /* HAVE_WINDOW_SYSTEM */ } diff --git a/src/frame.h b/src/frame.h index 1d920d1a6bc..7c2d82c1be3 100644 --- a/src/frame.h +++ b/src/frame.h @@ -258,6 +258,9 @@ #define EMACS_FRAME_H /* Desired and current contents displayed in that window. */ Lisp_Object desired_tab_bar_string; Lisp_Object current_tab_bar_string; + + /* Configuration for background image. */ + Lisp_Object background_policy; #endif #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR) @@ -741,6 +744,13 @@ #define EMACS_FRAME_H /* Text conversion state used by certain input methods. */ struct text_conversion_state conversion; #endif + +#ifdef HAVE_WINDOW_SYSTEM + ptrdiff_t background_image; + int background_gravity; + bool background_tiled; +#endif /* HAVE_WINDOW_SYSTEM */ + } GCALIGNED_STRUCT; /* Most code should use these functions to set Lisp fields in struct frame. */ diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 3700154e44a..dd019275f43 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -40,6 +40,8 @@ #ifdef HAVE_PGTK #include "xsettings.h" #endif +#include "complexbkg.h" + #ifdef USE_BE_CAIRO #define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) @@ -601,6 +603,12 @@ ftcrfont_draw (struct glyph_string *s, cairo_rectangle (cr, x, y - FONT_BASE (s->font), s->width, FONT_HEIGHT (s->font)); cairo_fill (cr); + + struct complexbkg_platform_info data = { s->f, s->gc };; + complexbkg_clear_frame_area (s->f, 0, + x, y - FONT_BASE (s->font), + s->width, FONT_HEIGHT (s->font), + &data ); } glyphs = alloca (sizeof (cairo_glyph_t) * len); diff --git a/src/w32font.c b/src/w32font.c index 48968a28fbd..30676e23ccc 100644 --- a/src/w32font.c +++ b/src/w32font.c @@ -24,6 +24,7 @@ #include <commdlg.h> #include "lisp.h" +#include "complexbkg.h" #include "w32term.h" #include "frame.h" #include "coding.h" /* for ENCODE_SYSTEM, DECODE_SYSTEM */ @@ -696,6 +697,7 @@ w32font_draw (struct glyph_string *s, int from, int to, - s->first_glyph->slice.glyphless.upper_yoff; descent = 0; } + brush = CreateSolidBrush (s->gc->background); rect.left = x; rect.top = y - ascent; @@ -703,6 +705,12 @@ w32font_draw (struct glyph_string *s, int from, int to, rect.bottom = y + descent; FillRect (s->hdc, &rect, brush); DeleteObject (brush); + + struct complexbkg_platform_info data = { s->hdc }; + + complexbkg_clear_frame_area (s->f, s->gc->background, + x, y - ascent, s->width, + ascent + descent, &data); } if (s->padding_p) diff --git a/src/w32term.c b/src/w32term.c index e18f39dd2a8..6663fa1d5e8 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -22,6 +22,7 @@ Copyright (C) 1989, 1993-2024 Free Software Foundation, Inc. #include <stdio.h> #include "lisp.h" #include "blockinput.h" +#include "complexbkg.h" #include "w32term.h" #include "w32common.h" /* for OS version info */ #include <wtypes.h> @@ -1285,8 +1286,11 @@ w32_clear_glyph_string_rect (struct glyph_string *s, - s->gc->clip_rectangle.top); } #endif - w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y, - real_w, real_h); + w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y, + real_w, real_h); + struct complexbkg_platform_info data = { s->hdc }; + complexbkg_clear_frame_area (s->f, s->gc->background, + real_x, real_y, real_w, real_h, &data); } /* Fill background with bitmap pattern from S at specified position @@ -2604,7 +2608,10 @@ w32_draw_stretch_glyph_string (struct glyph_string *s) } else { - w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h); + w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h); + struct complexbkg_platform_info data = { s->hdc }; + complexbkg_clear_frame_area (s->f, gc->background, + x, y, w, h, &data); } } } @@ -6626,7 +6633,6 @@ w32_draw_bar_cursor (struct window *w, struct glyph_row *row, } } - /* RIF: Define cursor CURSOR on frame F. */ static void @@ -6635,7 +6641,6 @@ w32_define_frame_cursor (struct frame *f, Emacs_Cursor cursor) w32_define_cursor (FRAME_W32_WINDOW (f), cursor); } - /* RIF: Clear area on frame F. */ static void @@ -6644,7 +6649,12 @@ w32_clear_frame_area (struct frame *f, int x, int y, int width, int height) HDC hdc; hdc = get_frame_dc (f); + w32_clear_area (f, hdc, x, y, width, height); + struct complexbkg_platform_info data = { hdc }; + complexbkg_clear_frame_area (f, FRAME_BACKGROUND_PIXEL(f), + x, y, width, height, &data); + release_frame_dc (f, hdc); } diff --git a/src/xterm.c b/src/xterm.c index 0c20d38b0f7..653dcfb2e8c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -719,6 +719,8 @@ Copyright (C) 1989, 1993-2024 Free Software Foundation, Inc. #include "sysselect.h" #include "menu.h" #include "pdumper.h" +#include "complexbkg.h" + #ifdef USE_X_TOOLKIT #include <X11/Shell.h> @@ -6288,7 +6290,7 @@ x_cr_destroy_fringe_bitmap (int which) fringe_bmp[which] = 0; } -static void +void x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image, int src_x, int src_y, int width, int height, int dest_x, int dest_y, bool overlay_p) @@ -8530,6 +8532,8 @@ x_compute_glyph_string_overhangs (struct glyph_string *s) x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) { x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR); + struct complexbkg_platform_info data = { s->f, s->gc }; + complexbkg_clear_frame_area (s->f, 0, x, y, w, h, &data); } #ifndef USE_CAIRO @@ -10713,6 +10717,10 @@ x_draw_stretch_glyph_string (struct glyph_string *s) XSetForeground (display, gc, xgcv.background); x_fill_rectangle (s->f, gc, x, y, w, h, true); XSetForeground (display, gc, xgcv.foreground); + + struct complexbkg_platform_info data = { s->f, gc }; + complexbkg_clear_frame_area (s->f, 0, + x, y, w, h, &data); } x_reset_clip_rectangles (s->f, gc); @@ -26039,6 +26047,9 @@ x_define_frame_cursor (struct frame *f, Emacs_Cursor cursor) x_clear_frame_area (struct frame *f, int x, int y, int width, int height) { x_clear_area (f, x, y, width, height); + struct complexbkg_platform_info data = { f, NULL }; + complexbkg_clear_frame_area (f, FRAME_BACKGROUND_PIXEL(f), + x, y, width, height, &data); } diff --git a/src/xterm.h b/src/xterm.h index 8d5c9917749..ca7c745b369 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1816,6 +1816,9 @@ #define SELECTION_EVENT_TIME(eventp) \ extern void x_set_cr_source_with_gc_background (struct frame *, GC, bool); extern void x_cr_draw_frame (cairo_t *, struct frame *); extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t); +extern void x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image, + int src_x, int src_y, int width, int height, + int dest_x, int dest_y, bool overlay_p); #endif #ifdef HAVE_XFIXES -- 2.35.1.windows.2 [-- Attachment #3: emacs_R5JevGsu5Z.png --] [-- Type: image/png, Size: 35207 bytes --] [-- Attachment #4: msrdc_mtQ0HAdC5U.png --] [-- Type: image/png, Size: 50197 bytes --] ^ permalink raw reply related [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-08 13:59 ` Cecilio Pardo @ 2024-11-08 15:46 ` Eli Zaretskii 2024-11-08 16:42 ` Cecilio Pardo 0 siblings, 1 reply; 16+ messages in thread From: Eli Zaretskii @ 2024-11-08 15:46 UTC (permalink / raw) To: Cecilio Pardo; +Cc: 16992 > Date: Fri, 8 Nov 2024 14:59:20 +0100 > Cc: 16992@debbugs.gnu.org > From: Cecilio Pardo <cpardo@imayhem.com> > > Here is the incomplete patch that implements background images. Thanks. I'm not yet sure I understand the overall picture and its implications, hence the questions below. > It works by adding a call to complex_bkg_clear_frame_area on all > functions that clear the background. These are the functions for w32 > port. For the cairo port, they are parallel: > > w32_clear_frame_area, w32_clear_glyph_string_rect, > w32_draw_stretch_glyph_string, w32font_draw > > I know I'm missing at least w32_draw_image_glyph_string, but works well > enough for a test. > > To setup the backgroud image for a frame, you would do something like > this: > > (progn > (setq bkg (create-image "icons/hicolor/128x128/apps/emacs.png")) > (frame-set-background-image (selected-frame) bkg 'center nil) > (frame-set-background-policy (selected-frame) t)) So showing a vertical line for the fill-column indication would need to define a background image for a frame? How do we control the horizontal coordinate where the line is drawn? > The image can be placed in the center, or on sides or corners with 'n, > 's, 'se, 'sw, etc. The background can be filled be repeating the image > passing t as the last parameter of frame-set-background-image. Why not let Lisp specify explicit coordinates for the image? > Apart from the obvious overhead of drawing the image pixels, > unfortunately the frame contents can't be scrolled to reuse text pixels > (dispnew.c:scrolling_window). I don't think this can't be fixed without > big changes. Hmm.. scroll_run_hook is also called from two redisplay optimizations in xdisp.c, so those will need to be disabled as well. Too bad. But maybe we can make them work if we consider the background image to be scrolled together with the text? "all we need" is to insert a slice of the same image from below or from above, depending on the scrolling direction. Btw, what happens when text is scrolled horizontally? Is this only going to work with fixed images? Then I guess features like showing vertical lines as indentation indicators, like those here: https://techpress.net/how-to-show-hide-indent-dots-in-vscode/ will not be possible? > +get_all_live_windows (struct window *w, struct window **dest) > +{ > + if (WINDOW_LEAF_P (w)) > + { You could perhaps extend window_loop to do whatever the callers of this function do Thanks for working on this. ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-08 15:46 ` Eli Zaretskii @ 2024-11-08 16:42 ` Cecilio Pardo 2024-11-08 18:50 ` Eli Zaretskii 0 siblings, 1 reply; 16+ messages in thread From: Cecilio Pardo @ 2024-11-08 16:42 UTC (permalink / raw) To: 16992 On 08/11/2024 16:46, Eli Zaretskii wrote: > So showing a vertical line for the fill-column indication would need > to define a background image for a frame? How do we control the > horizontal coordinate where the line is drawn? No, the background image (if present) is drawn first, then 'dynamic' things like the indicator are drawn over, with the corresponding drawing api. We are doing both things. In the patch, the fill-column indicator line is drawn by looking directly at the value of fill_column. But I think it would be better to allow lisp to define multiple vertical lines, with the desired position. >> The image can be placed in the center, or on sides or corners with 'n, >> 's, 'se, 'sw, etc. The background can be filled be repeating the image >> passing t as the last parameter of frame-set-background-image. > > Why not let Lisp specify explicit coordinates for the image? Yes, I will add x/y offsets, to put it anywhere. >> Apart from the obvious overhead of drawing the image pixels, >> unfortunately the frame contents can't be scrolled to reuse text pixels >> (dispnew.c:scrolling_window). I don't think this can't be fixed without >> big changes. > > Hmm.. scroll_run_hook is also called from two redisplay optimizations > in xdisp.c, so those will need to be disabled as well. Too bad. > > But maybe we can make them work if we consider the background image to > be scrolled together with the text? "all we need" is to insert a slice > of the same image from below or from above, depending on the scrolling > direction. We can add scrolling images, sure. I think we should do both types then. > Btw, what happens when text is scrolled horizontally? Nothing special. Besides redrawing everything. > Is this only going to work with fixed images? Then I guess features > like showing vertical lines as indentation indicators, like those > here: > > https://techpress.net/how-to-show-hide-indent-dots-in-vscode/ > > will not be possible? Yes. Those are not part of the image. We use the same mechanism to draw on the background, but they are independent. We can use them without background images at all. Some of these things are easy to do, like the fill indicator, which doesn't depend on the contents of the buffer. Indentation lines are much more complex. If you find the mechanism to draw on the background acceptable, I can work on a first version of that. >> +get_all_live_windows (struct window *w, struct window **dest) >> +{ >> + if (WINDOW_LEAF_P (w)) >> + { > > You could perhaps extend window_loop to do whatever the callers of > this function do Ok, thanks. ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-08 16:42 ` Cecilio Pardo @ 2024-11-08 18:50 ` Eli Zaretskii 2024-11-08 19:20 ` Cecilio Pardo 0 siblings, 1 reply; 16+ messages in thread From: Eli Zaretskii @ 2024-11-08 18:50 UTC (permalink / raw) To: Cecilio Pardo; +Cc: 16992 > Date: Fri, 8 Nov 2024 17:42:48 +0100 > From: Cecilio Pardo <cpardo@imayhem.com> > > On 08/11/2024 16:46, Eli Zaretskii wrote: > > > So showing a vertical line for the fill-column indication would need > > to define a background image for a frame? How do we control the > > horizontal coordinate where the line is drawn? > > No, the background image (if present) is drawn first, then 'dynamic' > things like the indicator are drawn over, with the corresponding drawing > api. We are doing both things. In the patch, the fill-column indicator > line is drawn by looking directly at the value of fill_column. But I > think it would be better to allow lisp to define multiple vertical > lines, with the desired position. So what is the Lisp API for drawing those "dynamic" things? AFAIU, you've only shown the API to set a single static background image. > > Btw, what happens when text is scrolled horizontally? > > Nothing special. Besides redrawing everything. Is the background image scrolled or isn't it? > > Is this only going to work with fixed images? Then I guess features > > like showing vertical lines as indentation indicators, like those > > here: > > > > https://techpress.net/how-to-show-hide-indent-dots-in-vscode/ > > > > will not be possible? > > Yes. Those are not part of the image. We use the same mechanism to draw > on the background, but they are independent. We can use them without > background images at all. > > Some of these things are easy to do, like the fill indicator, which > doesn't depend on the contents of the buffer. Indentation lines are much > more complex. Those "dynamic" drawings are the most wanted feature that is currently missing. And the challenge is to implement them in a way that won't make redisplay significantly slower, e.g. due to disabled optimizations (like scrolling_window). ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-08 18:50 ` Eli Zaretskii @ 2024-11-08 19:20 ` Cecilio Pardo 2024-11-09 7:44 ` Eli Zaretskii 0 siblings, 1 reply; 16+ messages in thread From: Cecilio Pardo @ 2024-11-08 19:20 UTC (permalink / raw) To: 16992 On 08/11/2024 19:50, Eli Zaretskii wrote: > So what is the Lisp API for drawing those "dynamic" things? AFAIU, > you've only shown the API to set a single static background image. There is no lisp api yet. In this example the fill-column line is drawn always, in the part that iterates through the windows. > Is the background image scrolled or isn't it? No. The background image is always fixed at this point. > Those "dynamic" drawings are the most wanted feature that is currently > missing. And the challenge is to implement them in a way that won't > make redisplay significantly slower, e.g. due to disabled > optimizations (like scrolling_window). Then let's drop the image thing for now and focus on this. The two use cases I have right now imply just a series of vertical lines: - Lines fixed One to an x coordinate with an infinite height, for fill-column. - Segments distributed through the window for the indent-lines. We could have buffer local variables to define these lines. What other features should we consider? Should we open a new bug report to discuss this? ^ permalink raw reply [flat|nested] 16+ messages in thread
* bug#16992: feature request: background images 2024-11-08 19:20 ` Cecilio Pardo @ 2024-11-09 7:44 ` Eli Zaretskii 0 siblings, 0 replies; 16+ messages in thread From: Eli Zaretskii @ 2024-11-09 7:44 UTC (permalink / raw) To: Cecilio Pardo; +Cc: 16992 > Date: Fri, 8 Nov 2024 20:20:31 +0100 > From: Cecilio Pardo <cpardo@imayhem.com> > > On 08/11/2024 19:50, Eli Zaretskii wrote: > > So what is the Lisp API for drawing those "dynamic" things? AFAIU, > > you've only shown the API to set a single static background image. > > There is no lisp api yet. In this example the fill-column line is drawn > always, in the part that iterates through the windows. > > > Is the background image scrolled or isn't it? > > No. The background image is always fixed at this point. I could see use cases for optionally scrolling the background image as well. > > Those "dynamic" drawings are the most wanted feature that is currently > > missing. And the challenge is to implement them in a way that won't > > make redisplay significantly slower, e.g. due to disabled > > optimizations (like scrolling_window). > > Then let's drop the image thing for now and focus on this. We don't have to drop the background image feature. It has its place, IMO. But I think we should not consider it as a candidate for implementing dynamic drawings such as fill-column indicator. That should be a separate feature. > The two use cases I have right now imply just a series of vertical lines: > > - Lines fixed One to an x coordinate with an infinite height, for > fill-column. It is not fixed because its X coordinate is controlled from Lisp. In addition, if a buffer mixes LTR and RTL paragraphs, the indicator is shown sometimes on the right and sometimes on the left (because columns are counted right-to-left in an RTL paragraph). > - Segments distributed through the window for the indent-lines. > > We could have buffer local variables to define these lines. Yes. > What other features should we consider? Anything that needs some image to be drawn which partially or fully overlaps the usual buffer/string display. > Should we open a new bug report to discuss this? Probably. And I suggest to ask a question on emacs-devel. Over the years, there were quite a few requests for something like this, and there are several optional (mostly 3rd-party) packages which try to do this in Lisp (which require very complex Lisp code, and IMO look clunky and even unprofessional), so asking a question might bring additional interesting ideas for using this kind of functionality. Btw, all of these will need some way of enabling at least some redisplay optimizations, and at least for images which scroll together with the buffer that should be possible. ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-11-09 7:44 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-03-11 23:19 bug#16992: Feature request David Englund 2014-03-12 6:26 ` Glenn Morris 2020-08-04 9:50 ` Lars Ingebrigtsen 2021-11-05 13:42 ` bug#20647: bug#16992: feature request: background images Stefan Kangas [not found] ` <CALaEO5W3+aEtwPr7bt3zNbkNw386GXpE-vkoRoojS0HqOvDQkQ@mail.gmail.com> 2021-11-15 7:08 ` Stefan Kangas 2021-11-16 11:10 ` tadashi watanabe 2024-11-06 22:34 ` Cecilio Pardo 2024-11-07 1:43 ` Stefan Kangas 2024-11-07 6:46 ` Cecilio Pardo 2024-11-07 6:04 ` Eli Zaretskii 2024-11-08 13:59 ` Cecilio Pardo 2024-11-08 15:46 ` Eli Zaretskii 2024-11-08 16:42 ` Cecilio Pardo 2024-11-08 18:50 ` Eli Zaretskii 2024-11-08 19:20 ` Cecilio Pardo 2024-11-09 7:44 ` Eli Zaretskii
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).