"Kirill M. Katsnelson" <kkm(a)kis.ru> writes:
> I was going to implement a separate face for dividers, but there's a much
> better soultion: make the dividers 3-D, just like the modeline, what
> Jonathan actually did under Windows from the very beginning. I looked
> at the code which draws 3-D border around modeline, and understood that
> this is beyond my powers to do this myself. Any good soul out there can
> make this under X? Picture attached ;)
Here it is, picture attached ... (Kirill, please say it ... that I'm a
good soul ;-))
Currently, I see that all divider size parameters are hard-wired. So
I've hard-wired a shadow thickness value too. My plan is to make it a
specifier. That way, we'll be able to give the divider a `pressed' look when
we drag it. This patch must be applied on top of Kirill's.
1998-05-12 Didier Verna <verna(a)inf.enst.fr>
* redisplay-x.c (x_output_vertical_divider): draw shadows around
the divider line. The shadow thickness is currently
hard-wired. This will probably be turned into a specifier soon.
--- src/redisplay-x.c.orig Tue May 12 10:39:36 1998
+++ src/redisplay-x.c Tue May 12 13:19:22 1998
@@ -54,16 +54,22 @@
/* X_DIVIDER_LINE_WIDTH is the width of the line drawn in the gutter.
X_DIVIDER_SPACING is the amount of blank space on each side of the line.
- X_DIVIDER_WIDTH = X_DIVIDER_LINE_WIDTH + 2*X_DIVIDER_SPACING
+ X_DIVIDER_SHADOW_THICKNESS is the size of shadows
+ X_DIVIDER_WIDTH =
+ X_DIVIDER_LINE_WIDTH + 2*X_DIVIDER_SPACING + 2*X_DIVIDER_SHADOW_THICKNESS
*/
/* Number of pixels below each line. */
/* #### implement me */
int x_interline_space;
-#define X_DIVIDER_LINE_WIDTH 3
-#define X_DIVIDER_SPACING 2
-#define X_DIVIDER_WIDTH (X_DIVIDER_LINE_WIDTH + 2 * X_DIVIDER_SPACING)
+#define X_DIVIDER_LINE_WIDTH 3
+#define X_DIVIDER_SPACING 2
+#define X_DIVIDER_SHADOW_THICKNESS 2
+#define X_DIVIDER_WIDTH \
+ (X_DIVIDER_LINE_WIDTH + \
+ 2 * X_DIVIDER_SPACING + \
+ 2 * X_DIVIDER_SHADOW_THICKNESS)
#define EOL_CURSOR_WIDTH 5
@@ -1396,32 +1402,107 @@
struct frame *f = XFRAME (w->frame);
struct device *d = XDEVICE (f->device);
+ EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
Display *dpy = DEVICE_X_DISPLAY (d);
Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
- GC gc;
+ Pixel top_shadow_pixel, bottom_shadow_pixel, background_pixel;
+ Lisp_Object tmp_pixel;
+ XColor tmp_color;
+ XGCValues gcv;
+ GC top_shadow_gc, bottom_shadow_gc, background_gc;
+ int use_pixmap = 0;
+ int flip_gcs = 0;
+ unsigned long mask;
+
int x = WINDOW_RIGHT (w) - X_DIVIDER_WIDTH;
int y1 = WINDOW_TOP (w);
int y2 = WINDOW_BOTTOM (w);
+ memset (&gcv, ~0, sizeof (XGCValues));
+
+ tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, MODELINE_INDEX);
+ tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
+
+ /* First, get the GC's. */
+ top_shadow_pixel = tmp_color.pixel;
+ bottom_shadow_pixel = tmp_color.pixel;
+ background_pixel = tmp_color.pixel;
+
+ x_generate_shadow_pixels (f, &top_shadow_pixel, &bottom_shadow_pixel,
+ background_pixel, ef->core.background_pixel);
+
+ tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, MODELINE_INDEX);
+ tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
+ gcv.background = tmp_color.pixel;
+ gcv.graphics_exposures = False;
+ mask = GCForeground | GCBackground | GCGraphicsExposures;
+
+ /* If we can't distinguish one of the shadows (the color is the same as the
+ background), it's better to use a pixmap to generate a dithrered gray. */
+ if (top_shadow_pixel == background_pixel ||
+ bottom_shadow_pixel == background_pixel)
+ use_pixmap = 1;
+
+ if (use_pixmap)
+ {
+ if (DEVICE_X_GRAY_PIXMAP (d) == None)
+ {
+ DEVICE_X_GRAY_PIXMAP (d) =
+ XCreatePixmapFromBitmapData (dpy, x_win, (char *) gray_bits,
+ gray_width, gray_height, 1, 0, 1);
+ }
+
+ tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, MODELINE_INDEX);
+ tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
+ gcv.foreground = tmp_color.pixel;
+ /* this is needed because the GC draws with a pixmap here */
+ gcv.fill_style = FillOpaqueStippled;
+ gcv.stipple = DEVICE_X_GRAY_PIXMAP (d);
+ top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv,
+ (mask | GCStipple | GCFillStyle));
+
+ tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, MODELINE_INDEX);
+ tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
+ bottom_shadow_pixel = tmp_color.pixel;
+
+ flip_gcs = (bottom_shadow_pixel ==
+ WhitePixelOfScreen (DefaultScreenOfDisplay (dpy)));
+ }
+ else
+ {
+ gcv.foreground = top_shadow_pixel;
+ top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
+ }
+
+ gcv.foreground = bottom_shadow_pixel;
+ bottom_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
+
+ if (use_pixmap && flip_gcs)
+ {
+ GC tmp_gc = bottom_shadow_gc;
+ bottom_shadow_gc = top_shadow_gc;
+ top_shadow_gc = tmp_gc;
+ }
+
+ gcv.foreground = background_pixel;
+ background_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
+
/* Clear the divider area first. This needs to be done when a
window split occurs. */
if (clear)
XClearArea (dpy, x_win, x, y1, X_DIVIDER_WIDTH, y2 - y1, False);
- /* #### There needs to be some checks to make sure that whatever
- colors we choose, the line will be visible (not same color as
- default background.
-
- #### No there don't. If I want the vertical divider to be
- invisible, I should be able to make it so. */
- gc = x_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, MODELINE_INDEX),
- WINDOW_FACE_CACHEL_BACKGROUND (w, MODELINE_INDEX),
- Qnil, Qnil);
-
/* Draw the divider line. */
- XFillRectangle (dpy, x_win, gc, x + X_DIVIDER_SPACING, y1,
+ XFillRectangle (dpy, x_win, background_gc,
+ x + X_DIVIDER_SPACING + X_DIVIDER_SHADOW_THICKNESS, y1,
X_DIVIDER_LINE_WIDTH, y2 - y1);
+
+ /* Draw the shadows around the divider line */
+ x_output_shadows (f, x + X_DIVIDER_SPACING, y1,
+ X_DIVIDER_WIDTH - 2 * X_DIVIDER_SPACING, y2 - y1,
+ top_shadow_gc, bottom_shadow_gc,
+ background_gc, X_DIVIDER_SHADOW_THICKNESS);
}
/*****************************************************************************