1
/* frames.c -- window frame manipulation
2
$Id: frames.c,v 1.101 2001/02/20 00:04:57 jsh Exp $
4
Copyright (C) 1999, 2000 John Harper <john@dcs.warwick.ac.uk>
6
This file is part of sawmill.
8
sawmill is free software; you can redistribute it and/or modify it
9
under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2, or (at your option)
13
sawmill is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with sawmill; see the file COPYING. If not, write to
20
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
/* AIX requires this to be the first thing in the file. */
33
# ifndef alloca /* predefined by HP cc +Olibcalls */
41
#include <X11/Xutil.h>
42
#include <X11/Xresource.h>
43
#include <X11/extensions/shape.h>
46
static XID window_fp_context;
49
static struct frame_part *allocated_parts;
51
DEFSYM(internal, "internal");
52
DEFSYM(tiled, "tiled");
53
DEFSYM(center, "center");
54
DEFSYM(right, "right");
57
DEFSYM(bottom, "left");
59
DEFSYM(x_justify, "x-justify");
60
DEFSYM(y_justify, "y-justify");
61
DEFSYM(background, "background");
62
DEFSYM(foreground, "foreground");
63
DEFSYM(renderer, "renderer");
64
DEFSYM(render_scale, "render-scale");
66
DEFSYM(width, "width");
67
DEFSYM(height, "height");
68
DEFSYM(left_edge, "left-edge");
69
DEFSYM(top_edge, "top-edge");
70
DEFSYM(right_edge, "right-edge");
71
DEFSYM(bottom_edge, "bottom-edge");
72
DEFSYM(cursor, "cursor");
73
DEFSYM(focused, "focused");
74
DEFSYM(highlighted, "highlighted");
75
DEFSYM(clicked, "clicked");
76
DEFSYM(inactive, "inactive");
77
DEFSYM(inactive_highlighted, "inactive-highlighted");
78
DEFSYM(inactive_clicked, "inactive-clicked");
79
DEFSYM(hide_client, "hide-client");
80
DEFSYM(class, "class");
81
DEFSYM(removable, "removable");
82
DEFSYM(removed_classes, "removed-classes");
83
DEFSYM(frame_part_classes, "frame-part-classes");
84
DEFSYM(override_frame_part_classes, "override-frame-part-classes");
85
DEFSYM(below_client, "below-client");
86
DEFSYM(scale_foreground, "scale-foreground");
87
DEFSYM(hidden, "hidden");
89
static repv state_syms[fps_MAX];
91
static bool frame_draw_mutex;
92
bool frame_state_mutex;
97
static struct frame_part *
98
fp_new (Lisp_Window *win, repv alist)
100
struct frame_part *fp = rep_ALLOC_CELL (sizeof (struct frame_part));
101
rep_data_after_gc += sizeof (struct frame_part);
102
memset (fp, 0, sizeof (struct frame_part));
103
fp->car = frame_part_type;
106
fp->local_alist = Qnil;
107
fp->next_alloc = allocated_parts;
108
allocated_parts = fp;
113
fp_cmp (repv w1, repv w2)
119
fp_prin (repv stream, repv win)
122
sprintf (buf, "#<frame-part %lx>", VPART(win)->id);
123
rep_stream_puts (stream, buf, -1, FALSE);
129
struct frame_part *fp;
130
for (fp = VPART(obj); fp != 0; fp = fp->next)
133
rep_MARKVAL(fp->alist);
134
rep_MARKVAL(fp->local_alist);
135
rep_MARKVAL(rep_VAL(fp->win));
136
for (i = 0; i < fps_MAX; i++)
138
rep_MARKVAL(fp->font[i]);
139
rep_MARKVAL(fp->fg[i]);
140
rep_MARKVAL(fp->bg[i]);
142
rep_MARKVAL(rep_VAL(fp->cursor));
143
rep_MARKVAL(rep_VAL(fp->renderer));
144
rep_MARKVAL(rep_VAL(fp->rendered_image));
145
rep_MARKVAL(fp->drawn.font);
146
rep_MARKVAL(fp->drawn.text);
147
rep_MARKVAL(fp->drawn.x_justify);
148
rep_MARKVAL(fp->drawn.y_justify);
149
rep_MARKVAL(fp->drawn.fg);
150
rep_MARKVAL(fp->drawn.bg);
157
struct frame_part *fp = allocated_parts;
161
struct frame_part *next = fp->next_alloc;
162
if (!rep_GC_CELL_MARKEDP(rep_VAL(fp)))
164
assert (fp->next == 0);
165
assert (fp->id == 0);
167
/* XXX This assertion has been reported to trigger (when opening
168
ddd and acroread -- both motif apps?). I don't see how this
169
happens but since fp->id is zero and fp->win will get gc'd,
170
we're not going to leak any resources, so.. */
171
assert (fp->win == 0);
177
fp->next_alloc = allocated_parts;
178
allocated_parts = fp;
179
rep_GC_CLR_CELL(rep_VAL(fp));
186
/* building frames from component lists
188
build the frame from the list of components. Each element
189
in the list is an alist representing one component of the
190
frame, possible tags include:
194
background . IMAGE-OR-COLOR
195
background . (NORMAL FOCUSED HIGHLIGHTED CLICKED)
196
background . ((STATE . VALUE) ...)
198
foreground . (NORMAL FOCUSED HIGHLIGHTED CLICKED)
199
foreground . ((STATE . VALUE) ...)
202
render-scale . INTEGER
204
text . STRING-OR-FUNCTION-OR-NIL
205
x-justify . left OR right OR center OR NUMBER
206
y-justify . top OR bottom OR center OR NUMBER
209
font . (NORMAL FOCUSED HIGHLIGHTED CLICKED)
210
font . ((STATE . FONT) ...)
212
left-edge . POSITION-REL-LEFT
213
right-edge . POSITION-REL-RIGHT
214
top-edge . POSITION-REL-TOP
215
bottom-edge . POSITION-REL-BOTTOM
220
cursor . CURSOR-OR-CURSOR-DEF
225
STATE's are one of: inactive, focused, highlighted, clicked,
226
inactive-highlighted, inactive-clicked.
228
Note that all numeric quantities may be defined dynamically by
229
substituting a function */
232
current_state (struct frame_part *fp)
236
if (fp->win == focus_window)
239
return fps_inactive_clicked;
241
else if (fp->highlighted)
243
if (fp->win == focus_window)
244
return fps_highlighted;
246
return fps_inactive_highlighted;
248
else if (fp->win == focus_window)
254
/* Call FUN (ARG) with error protection in place. If an error occurs
255
a message is printed, and ERROR-RETURN is returned, else just return
256
the result of calling FUN. */
258
call_protectedly (repv (*fun)(repv), repv arg, repv error_return)
260
rep_GC_root gc_error_return;
262
rep_PUSHGC (gc_error_return, error_return);
264
if (result == rep_NULL)
266
repv throw = rep_throw_value, stream;
267
rep_throw_value = rep_NULL;
268
stream = Fstderr_file();
269
if (stream != rep_NULL)
271
rep_stream_puts (stream, "frame error: ", -1, rep_FALSE);
272
if (rep_CAR (throw) == Qerror)
273
throw = rep_CDR (throw);
274
rep_print_val (stream, throw);
275
rep_stream_putc (stream, '\n');
277
result = error_return;
283
/* Call lisp function FUN with the single arg ARG, with error protection */
285
call_protectedly_1 (repv fun, repv arg, repv error_return)
287
return call_protectedly (Ffuncall, rep_LIST_2 (fun, arg), error_return);
291
apply_mask (Drawable dest, int x_off, int y_off,
292
int dest_width, int dest_height,
293
Pixmap src, int src_width, int src_height)
295
if (dest_width - x_off >= src_width
296
&& dest_height - y_off >= src_height)
298
/* No need for a temporary buffer */
299
XShapeCombineMask (dpy, dest, ShapeBounding,
300
x_off, y_off, src, ShapeUnion);
304
Pixmap tem = XCreatePixmap (dpy, src, dest_width - x_off,
305
dest_height - y_off, 1);
307
GC gc = XCreateGC (dpy, tem, 0, &gcv);
308
XCopyArea (dpy, src, tem, gc, 0, 0,
309
dest_width - x_off, dest_height - y_off, 0, 0);
310
XShapeCombineMask (dpy, dest, ShapeBounding,
311
x_off, y_off, tem, ShapeUnion);
313
XFreePixmap (dpy, tem);
317
/* Construct the frame window's shape mask from the union of all
318
individual shapes (frame parts and the client window, if appropriate).
319
If ATOMIC is true, then the frame shape is changed _once_ only, using
320
a temporary buffer to construct the new shape, then copying it
323
set_frame_shapes (Lisp_Window *w, bool atomic)
328
struct frame_part *fp;
332
XSetWindowAttributes wa;
334
wa.colormap = image_cmap;
335
wa.border_pixel = BlackPixel (dpy, screen_num);
336
wamask = CWColormap | CWBorderPixel;
337
shape_win = XCreateWindow (dpy, root_window, -100, -100,
338
w->frame_width, w->frame_height,
339
0, image_depth, InputOutput,
340
image_visual, wamask, &wa);
343
shape_win = w->frame;
346
for (fp = w->frame_parts; fp != 0; fp = fp->next)
349
rects = alloca (sizeof (XRectangle) * (nparts + 1));
351
rects[0].x = rects[0].y = 0;
352
rects[0].width = w->frame_width;
353
rects[0].height = w->frame_height;
354
XShapeCombineRectangles (dpy, shape_win, ShapeBounding,
355
0, 0, rects, 1, ShapeSubtract, Unsorted);
357
if (!w->client_hidden)
361
XShapeCombineShape (dpy, shape_win, ShapeBounding,
362
-w->frame_x, -w->frame_y, w->id,
363
ShapeBounding, ShapeSet);
367
rects[nrects].x = -w->frame_x;
368
rects[nrects].y = -w->frame_y;
369
rects[nrects].width = w->attr.width;
370
rects[nrects].height = w->attr.height;
375
for (fp = w->frame_parts; fp != 0 && !WINDOW_IS_GONE_P (w); fp = fp->next)
378
int state = current_state (fp);
380
if (fp->width <= 0 || fp->height <= 0)
383
if (IMAGEP(fp->bg[state]))
386
Lisp_Image *image = VIMAGE(fp->bg[state]);
389
tem = Fimage_get (rep_VAL(image), Qtiled);
390
if (tem && tem != Qnil)
395
image_render (image, image_width (image), image_height (image),
400
image_render (image, fp->width, fp->height, &pixmap, &mask);
405
int width = !tiled ? fp->width : image_width (image);
406
int height = !tiled ? fp->height : image_height (image);
407
int x_off = fp->x - w->frame_x;
408
int y_off = fp->y - w->frame_y;
410
apply_mask (shape_win, x_off, y_off,
411
x_off + fp->width, y_off + fp->height,
412
mask, width, height);
416
int x = width, y = 0;
417
while (y < fp->height)
419
while (x < fp->width)
421
apply_mask (shape_win, x_off + x, y_off + y,
422
x_off + fp->width, y_off + fp->height,
423
mask, width, height);
433
rects[nrects].x = fp->x - w->frame_x;
434
rects[nrects].y = fp->y - w->frame_y;
435
rects[nrects].width = fp->width;
436
rects[nrects].height = fp->height;
439
image_free_pixmaps (image, pixmap, mask);
443
rects[nrects].x = fp->x - w->frame_x;
444
rects[nrects].y = fp->y - w->frame_y;
445
rects[nrects].width = fp->width;
446
rects[nrects].height = fp->height;
453
XShapeCombineRectangles (dpy, shape_win, ShapeBounding, 0, 0, rects,
454
nrects, ShapeUnion, Unsorted);
459
XShapeCombineShape (dpy, w->frame, ShapeBounding,
460
0, 0, shape_win, ShapeBounding, ShapeSet);
461
XDestroyWindow (dpy, shape_win);
464
w->pending_reshape = 0;
467
/* Queue an atomic reshape for the frame of W. It will happen sometime
468
in the near future. */
470
queue_reshape_frame (Lisp_Window *w)
472
w->pending_reshape = 1;
476
commit_queued_reshapes (void)
479
for (w = window_list; w != 0; w = w->next)
481
if (!WINDOW_IS_GONE_P (w) && w->pending_reshape)
482
set_frame_shapes (w, TRUE);
486
/* Draw the background of the frame-part FP. This is either a solid color
487
or an image (scaled or tiled) */
489
set_frame_part_bg (struct frame_part *fp)
491
int state = current_state (fp);
492
repv bg = fp->bg[state];
493
Lisp_Window *win = fp->win;
498
if (fp->renderer != Qnil && IMAGEP(fp->rendered_image))
500
bg = fp->rendered_image;
501
if (fp->rendered_state != state)
503
rep_call_lisp2 (fp->renderer, bg, state_syms[state]);
504
fp->rendered_state = state;
509
if (WINDOW_IS_GONE_P (win))
514
if (bg != fp->drawn.bg)
517
gcv.foreground = VCOLOR(bg)->pixel;
518
XChangeGC (dpy, fp->gc, GCForeground, &gcv);
519
XFillRectangle (dpy, fp->id, fp->gc, 0, 0, fp->width, fp->height);
521
fp->drawn.fg = rep_NULL;
526
Lisp_Image *image = VIMAGE(bg);
527
Pixmap bg_pixmap, bg_mask;
531
if (fp->drawn.bg == bg)
534
tem = Fimage_get (rep_VAL(image), Qtiled);
535
if (tem && tem != Qnil)
540
image_render (image, image_width (image), image_height (image),
541
&bg_pixmap, &bg_mask);
545
image_render (image, fp->width, fp->height, &bg_pixmap, &bg_mask);
548
/* Some of the Imlib_ functions call XSync on our display. In turn
549
this can cause the error handler to run if a window has been
550
deleted. This then invalidates the window we're updating */
551
if (WINDOW_IS_GONE_P (win))
556
/* No mask, so we always want to force the rectangle
557
including the frame part to be shown.. */
560
rect.width = fp->width;
561
rect.height = fp->height;
562
XShapeCombineRectangles (dpy, fp->id, ShapeBounding,
563
0, 0, &rect, 1, ShapeSet, Unsorted);
568
XCopyArea (dpy, bg_pixmap, fp->id, fp->gc, 0, 0,
569
fp->width, fp->height, 0, 0);
572
XShapeCombineMask (dpy, fp->id, ShapeBounding,
573
0, 0, bg_mask, ShapeSet);
583
XSetWindowAttributes wa;
585
wa.colormap = image_cmap;
586
wa.border_pixel = BlackPixel (dpy, screen_num);
587
wamask = CWColormap | CWBorderPixel;
588
tem = XCreateWindow (dpy, win->frame, -100, -100,
589
fp->width, fp->height,
590
0, image_depth, InputOutput,
591
image_visual, wamask, &wa);
593
rect.width = fp->width;
594
rect.height = fp->height;
595
XShapeCombineRectangles (dpy, tem, ShapeBounding, 0, 0,
596
&rect, 1, ShapeSubtract, Unsorted);
598
while (y < fp->height)
601
int width = image_width (image);
602
int height = image_height (image);
603
while (x < fp->width)
605
XCopyArea (dpy, bg_pixmap, fp->id, fp->gc,
606
0, 0, width, height, x, y);
609
XShapeCombineMask (dpy, tem, ShapeBounding,
610
x, y, bg_mask, ShapeUnion);
618
XShapeCombineShape (dpy, fp->id, ShapeBounding, 0, 0,
619
tem, ShapeBounding, ShapeSet);
620
XDestroyWindow (dpy, tem);
623
image_free_pixmaps (image, bg_pixmap, bg_mask);
625
/* Imlib sometimes calls XSync (), which could hide events
627
rep_mark_input_pending (ConnectionNumber(dpy));
630
fp->drawn.fg = rep_NULL;
632
queue_reshape_frame (fp->win);
634
else if (Ffunctionp (bg) != Qnil)
636
rep_call_lisp1 (bg, rep_VAL(fp));
638
fp->drawn.fg = rep_NULL;
644
/* Draw the foreground pixels in frame-part FP. */
646
set_frame_part_fg (struct frame_part *fp)
648
int state = current_state (fp);
649
repv font = fp->font[state], fg = fp->fg[state];
652
repv string = rep_NULL;
653
int length = 0, width, height, x, y;
654
Lisp_Window *win = fp->win;
659
if (fg != Qnil && Ffunctionp (fg) != Qnil)
661
rep_call_lisp1 (fg, rep_VAL(fp));
663
else if (IMAGEP(fg) || fp->text != Qnil)
665
if (!COLORP(fg) && !IMAGEP(fg))
666
fg = global_symbol_value (Qdefault_foreground);
669
font = global_symbol_value (Qdefault_font);
676
if (fp->scale_foreground)
683
width = image_width (VIMAGE(fg));
684
height = image_height (VIMAGE(fg));
689
if (rep_STRINGP(fp->text))
692
length = rep_STRING_LEN(fp->text);
696
repv result = rep_call_lisp1 (fp->text, rep_VAL(fp->win));
697
if (!result || !rep_STRINGP(result))
700
length = rep_STRING_LEN(result);
703
width = x_text_width (font, rep_STR(string), length);
704
height = VFONT(font)->ascent + VFONT(font)->descent;
707
if (fp->x_justify == Qcenter)
708
x = MAX(0, (fp->width - width) / 2);
709
else if (fp->x_justify == Qright)
710
x = MAX(0, fp->width - width);
711
else if (rep_INTP(fp->x_justify))
713
x = rep_INT(fp->x_justify);
715
x = MAX(0, fp->width + x - width);
720
if (fp->y_justify == Qcenter)
721
y = MAX(0, (fp->height - height) / 2);
722
else if (fp->y_justify == Qbottom)
723
y = MAX(0, fp->height - height);
724
else if (rep_INTP(fp->y_justify))
726
y = rep_INT(fp->y_justify);
728
y = MAX(0, fp->height + y - height);
735
Pixmap fg_pixmap, fg_mask;
737
if (fp->drawn.fg == fg
738
&& fp->drawn.x_justify == fp->x_justify
739
&& fp->drawn.y_justify == fp->y_justify)
743
else if (fp->drawn.fg != rep_NULL)
745
/* there's something drawn in this part already,
746
update the background to clear it */
747
fp->drawn.bg = rep_NULL;
748
set_frame_part_bg (fp);
751
image_render (VIMAGE(fg), width, height,
752
&fg_pixmap, &fg_mask);
754
/* Some of the Imlib_ functions call XSync on our display. In turn
755
this can cause the error handler to run if a window has been
756
deleted. This then invalidates the window we're updating */
757
if (WINDOW_IS_GONE_P (win))
764
gcv.clip_mask = fg_mask;
765
gcv.clip_x_origin = x;
766
gcv.clip_y_origin = y;
767
gcv_mask |= GCClipMask | GCClipXOrigin | GCClipYOrigin;
770
XChangeGC (dpy, fp->gc, gcv_mask, &gcv);
771
XCopyArea (dpy, fg_pixmap, fp->id, fp->gc,
772
0, 0, MIN(fp->width, width),
773
MIN(fp->height, height), x, y);
776
gcv.clip_mask = None;
777
gcv.clip_x_origin = 0;
778
gcv.clip_y_origin = 0;
779
XChangeGC (dpy, fp->gc, GCClipMask | GCClipXOrigin
780
| GCClipYOrigin, &gcv);
782
image_free_pixmaps (VIMAGE(fg), fg_pixmap, fg_mask);
784
/* Imlib sometimes calls XSync (), which could hide events
786
rep_mark_input_pending (ConnectionNumber(dpy));
788
fp->drawn.text = Qnil;
790
else if (COLORP(fg) && FONTP(font))
792
if ((fp->drawn.text == string
793
|| Fequal (fp->drawn.text, string) != Qnil)
794
&& fp->drawn.font == font && fp->drawn.fg == fg
795
&& fp->drawn.x_justify == fp->x_justify
796
&& fp->drawn.y_justify == fp->y_justify)
800
else if (fp->drawn.fg != rep_NULL)
802
/* there's something drawn in this part already,
803
update the background to clear it */
804
fp->drawn.bg = rep_NULL;
805
set_frame_part_bg (fp);
810
gcv.foreground = VCOLOR(fg)->pixel;
811
gcv_mask |= GCForeground;
814
XChangeGC (dpy, fp->gc, gcv_mask, &gcv);
815
x_draw_string (fp->id, font, fp->gc, x, y + VFONT(font)->ascent,
816
rep_STR(string), length);
818
fp->drawn.text = string;
822
fp->drawn.font = font;
824
fp->drawn.x_justify = fp->x_justify;
825
fp->drawn.y_justify = fp->y_justify;
830
refresh_frame_part (struct frame_part *fp)
832
if (!frame_draw_mutex)
834
Lisp_Window *w = fp->win;
835
if (w == 0) /* XXX why is this needed? */
838
if (fp->drawn.width != fp->width || fp->drawn.height != fp->height)
839
fp->drawn.bg = rep_NULL;
841
if (!WINDOW_IS_GONE_P (w) && fp->id != 0)
842
set_frame_part_bg (fp);
843
if (!WINDOW_IS_GONE_P (w) && fp->id != 0)
844
set_frame_part_fg (fp);
846
fp->drawn.width = fp->width;
847
fp->drawn.height = fp->height;
848
fp->pending_refresh = 0;
851
fp->pending_refresh = 1;
854
/* Redraw frame parts in W. */
856
refresh_frame_parts (Lisp_Window *w)
858
struct frame_part *fp;
859
for (fp = w->frame_parts; !WINDOW_IS_GONE_P (w) && fp != 0; fp = fp->next)
860
refresh_frame_part (fp);
863
/* Find the frame-part that is drawn in window ID */
865
find_frame_part_by_window (Window id)
867
struct frame_part *fp;
868
return XFindContext (dpy, id, window_fp_context, (XPointer *)&fp) ? 0 : fp;
871
/* Destroy the window frame of W, assuming it's a frame-part derived frame */
873
frame_part_destroyer (Lisp_Window *w)
875
struct frame_part *fp, *next;
876
for (fp = w->frame_parts; fp != 0; fp = next)
880
/* This is necessary so that clicked_frame_part is cleared. */
881
bool old_mutex = frame_draw_mutex;
882
frame_draw_mutex = TRUE;
883
unclick_current_fp ();
884
XUngrabPointer (dpy, last_event_time);
885
frame_draw_mutex = old_mutex;
890
XFreeGC (dpy, fp->gc);
896
XDeleteContext (dpy, fp->id, window_fp_context);
897
XDestroyWindow (dpy, fp->id);
908
/* Handle the expose event EV for the frame part FP. */
910
frame_part_exposer (XExposeEvent *ev, struct frame_part *fp)
914
/* expose events override the drawing mutex,
915
unless the server is grabbed.. */
916
bool old_mutex = frame_draw_mutex;
917
frame_draw_mutex = (Fserver_grabbed_p () != Qnil);
918
fp->drawn.bg = rep_NULL;
919
refresh_frame_part (fp);
920
frame_draw_mutex = old_mutex;
925
fp_assq (struct frame_part *fp, repv prop,
926
repv class_alist, repv ov_class_alist)
930
tem = Fassq (prop, fp->local_alist);
931
if (tem && tem != Qnil)
934
tem = Fassq (prop, ov_class_alist);
935
if (tem && tem != Qnil)
938
tem = Fassq (prop, fp->alist);
939
if (tem && tem != Qnil)
942
tem = Fassq (prop, class_alist);
943
if (tem && tem != Qnil)
950
x_fp_assq (struct frame_part *fp, repv prop)
952
repv ret = Qnil, class, tem;
954
ret = Fassq (prop, fp->local_alist);
955
if (ret && ret != Qnil)
958
class = Fassq (Qclass, fp->alist);
959
if (class && class != Qnil)
960
class = rep_CDR(class);
964
tem = global_symbol_value (Qoverride_frame_part_classes);
965
if (class != rep_NULL && rep_CONSP(tem))
967
tem = Fassq (class, tem);
968
if (tem && tem != Qnil)
969
ret = Fassq (prop, rep_CDR(tem));
972
if (ret && ret == Qnil)
973
ret = Fassq (prop, fp->alist);
975
if (ret && ret == Qnil)
977
tem = global_symbol_value (Qframe_part_classes);
978
if (class != rep_NULL && rep_CONSP(tem))
980
tem = Fassq (class, tem);
981
if (tem && tem != Qnil)
982
ret = Fassq (prop, rep_CDR(tem));
986
return ret ? ret : Qnil;
990
get_integer_prop (struct frame_part *fp, repv prop, repv class, repv ov_class)
992
repv tem = fp_assq (fp, prop, class, ov_class);
993
if (tem && tem != Qnil)
995
if (rep_INTP(rep_CDR(tem)))
998
tem = call_protectedly_1 (rep_CDR(tem), rep_VAL(fp->win), Qnil);
999
return rep_INTP(tem) ? tem : Qnil;
1006
get_boolean_prop (struct frame_part *fp, repv prop, repv class, repv ov_class)
1008
repv tem = fp_assq (fp, prop, class, ov_class);
1009
if (tem && tem != Qnil)
1011
if (Ffunctionp (rep_CDR(tem)) == Qnil)
1014
tem = call_protectedly_1 (rep_CDR(tem), rep_VAL(fp->win), Qnil);
1022
get_pattern_prop (struct frame_part *fp, repv *data, repv (*conv)(repv data),
1023
repv prop, repv class, repv ov_class)
1028
tem = fp_assq (fp, prop, class, ov_class);
1031
if (Ffunctionp (rep_CDR(tem)) != Qnil)
1032
tem = call_protectedly_1 (rep_CDR(tem), rep_VAL(fp->win), Qnil);
1035
if (!rep_CONSP(tem))
1037
/* single value pattern */
1039
for (i = 1; i < fps_MAX; i++)
1042
else if (!rep_CONSP(rep_CAR(tem)))
1044
/* list of four elements: (NORMAL FOCUSED HIGHLIGHTED CLICKED) */
1046
static int map[4] = {
1047
fps_inactive, fps_focused, fps_highlighted, fps_clicked
1050
for (i = 0; i < 4; i++)
1052
data[map[i]] = rep_CAR(tem);
1053
if (rep_CONSP(rep_CDR(tem)))
1059
/* alist of elements (STATE . VALUE) */
1061
while (rep_CONSP(tem) && rep_CONSP(rep_CAR(tem)))
1063
repv state = rep_CAR(rep_CAR(tem));
1066
if (state == Qinactive)
1068
else if (state == Qfocused)
1070
else if (state == Qhighlighted)
1071
idx = fps_highlighted;
1072
else if (state == Qclicked)
1074
else if (state == Qinactive_highlighted)
1075
idx = fps_inactive_highlighted;
1076
else if (state == Qinactive_clicked)
1077
idx = fps_inactive_clicked;
1078
if (idx != fps_none)
1079
data[idx] = rep_CDR(rep_CAR(tem));
1085
/* now handle string conversions */
1086
for (i = 0; i < fps_MAX; i++)
1088
if (rep_STRINGP(data[i]))
1089
data[i] = call_protectedly (conv, data[i], Qnil);
1092
/* now fill any gaps in the state table */
1093
for (i = 0; i < fps_MAX; i++)
1095
static int map[fps_MAX] = {
1096
fps_inactive, fps_inactive, fps_focused,
1097
fps_inactive, fps_highlighted, fps_inactive_highlighted
1100
if (data[i] == Qnil)
1101
data[i] = data[map[i]];
1108
build_frame_part (struct frame_part *fp)
1110
Lisp_Window *w = fp->win;
1111
repv class = Qnil, class_elt = Qnil, ov_class_elt = Qnil, tem;
1112
rep_GC_root gc_class, gc_class_elt, gc_ov_class_elt;
1113
bool had_left_edge = FALSE, had_top_edge = FALSE;
1114
bool had_right_edge = FALSE, had_bottom_edge = FALSE;
1118
rep_PUSHGC(gc_class, class);
1119
rep_PUSHGC(gc_class_elt, class_elt);
1120
rep_PUSHGC(gc_ov_class_elt, ov_class_elt);
1122
fp->width = fp->height = -1;
1123
for (i = 0; i < fps_MAX; i++)
1124
fp->fg[i] = fp->bg[i] = fp->font[i] = Qnil;
1126
/* find the class of the part, and the alists of class-local state */
1127
tem = Fassq (Qclass, fp->alist);
1128
if (tem && tem != Qnil)
1130
class = rep_CDR(tem);
1131
tem = global_symbol_value (Qframe_part_classes);
1134
tem = Fassq (class, tem);
1135
if (tem && tem != Qnil)
1136
class_elt = rep_CDR(tem);
1138
tem = global_symbol_value (Qoverride_frame_part_classes);
1141
tem = Fassq (class, tem);
1142
if (tem && tem != Qnil)
1143
ov_class_elt = rep_CDR(tem);
1147
/* do we ignore this part? */
1148
tem = get_boolean_prop (fp, Qhidden, class_elt, ov_class_elt);
1151
tem = Fassq (Qremovable, fp->alist);
1152
if (tem && tem != Qnil && rep_CDR(tem) != Qnil)
1154
tem = Fwindow_get (rep_VAL(w), Qremoved_classes); /* XXX hoist */
1155
if (tem && rep_CONSP(tem))
1157
tem = Fmemq (class, tem);
1158
if (tem && tem != Qnil)
1163
tem = get_boolean_prop (fp, Qbelow_client, class_elt, ov_class_elt);
1164
fp->below_client = (tem && tem != Qnil);
1165
tem = get_boolean_prop (fp, Qscale_foreground, class_elt, ov_class_elt);
1166
fp->scale_foreground = (tem && tem != Qnil);
1168
/* get text label */
1169
tem = fp_assq (fp, Qtext, class_elt, ov_class_elt);
1171
fp->text = rep_CDR(tem);
1174
tem = fp_assq (fp, Qx_justify, class_elt, ov_class_elt);
1178
if (Ffunctionp (tem) != Qnil)
1179
tem = call_protectedly_1 (tem, rep_VAL(w), Qnil);
1180
fp->x_justify = tem;
1183
fp->x_justify = Qnil;
1184
tem = fp_assq (fp, Qy_justify, class_elt, ov_class_elt);
1188
if (Ffunctionp (tem) != Qnil)
1189
tem = call_protectedly_1 (tem, rep_VAL(w), Qnil);
1190
fp->y_justify = tem;
1193
fp->y_justify = Qnil;
1197
tem = fp_assq (fp, Qcursor, class_elt, ov_class_elt);
1201
if (Ffunctionp (tem) != Qnil)
1202
tem = call_protectedly_1 (tem, rep_VAL (w), Qnil);
1203
if (!CURSORP(tem) && tem != Qnil)
1204
tem = call_protectedly (Fget_cursor, tem, Qnil);
1209
/* get renderer function */
1210
tem = fp_assq (fp, Qrenderer, class_elt, ov_class_elt);
1211
if (tem != Qnil && Ffunctionp (rep_CDR(tem)) != Qnil)
1213
fp->renderer = rep_CDR(tem);
1214
tem = get_integer_prop (fp, Qrender_scale, class_elt, ov_class_elt);
1215
if (tem != Qnil && rep_INT(tem) > 0)
1216
fp->render_scale = rep_INT(tem);
1218
fp->render_scale = 1;
1221
fp->renderer = Qnil;
1223
/* get background images or colors */
1224
if (!get_pattern_prop (fp, fp->bg, Fget_color,
1225
Qbackground, class_elt, ov_class_elt))
1230
/* get foreground colors or images */
1231
if (!get_pattern_prop (fp, fp->fg, Fget_color,
1232
Qforeground, class_elt, ov_class_elt))
1238
if (!get_pattern_prop (fp, fp->font, Fget_font,
1239
Qfont, class_elt, ov_class_elt))
1244
/* If we have a background image for this part, take it as
1245
the provisional dimensions of the part */
1246
for (i = 0; i < fps_MAX; i++)
1248
if (IMAGEP(fp->bg[i]))
1250
fp->width = image_width (VIMAGE(fp->bg[i]));
1251
fp->height = image_height (VIMAGE(fp->bg[i]));
1256
/* get dimensions.. */
1257
tem = get_integer_prop (fp, Qwidth, class_elt, ov_class_elt);
1259
fp->width = rep_INT(tem);
1260
tem = get_integer_prop (fp, Qheight, class_elt, ov_class_elt);
1262
fp->height = rep_INT(tem);
1263
tem = get_integer_prop (fp, Qleft_edge, class_elt, ov_class_elt);
1266
fp->x = rep_INT(tem);
1267
had_left_edge = TRUE;
1269
tem = get_integer_prop (fp, Qtop_edge, class_elt, ov_class_elt);
1272
fp->y = rep_INT(tem);
1273
had_top_edge = TRUE;
1275
tem = get_integer_prop (fp, Qright_edge, class_elt, ov_class_elt);
1278
had_right_edge = TRUE;
1280
fp->width = w->attr.width - rep_INT(tem) - fp->x;
1282
fp->x = w->attr.width - rep_INT(tem) - fp->width;
1284
tem = get_integer_prop (fp, Qbottom_edge, class_elt, ov_class_elt);
1287
had_bottom_edge = TRUE;
1289
fp->height = w->attr.height - rep_INT(tem) - fp->y;
1291
fp->y = w->attr.height - rep_INT(tem) - fp->height;
1299
/* try to remove edges sticking out of small windows. if a part
1300
specified by only one edge sticks out of the other edge, then
1303
if (had_right_edge && !had_left_edge && fp->x < 0)
1308
else if (had_left_edge && !had_right_edge
1309
&& fp->x + fp->width > w->attr.width)
1311
fp->width = w->attr.width - fp->x;
1314
if (had_bottom_edge && !had_top_edge && fp->y < 0)
1316
fp->height += fp->y;
1319
else if (had_top_edge && !had_bottom_edge
1320
&& fp->y + fp->height > w->attr.height)
1322
fp->height = w->attr.height - fp->y;
1325
/* if we have a renderer function, create the image to
1327
if (fp->renderer != Qnil)
1330
= Fmake_sized_image (rep_MAKE_INT(fp->width / fp->render_scale),
1331
rep_MAKE_INT(fp->height / fp->render_scale),
1333
fp->rendered_state = fps_none;
1336
fp->rendered_image = Qnil;
1338
DB((" part: x=%d y=%d width=%d height=%d\n",
1339
fp->x, fp->y, fp->width, fp->height));
1344
rep_POPGC; rep_POPGC; rep_POPGC;
1349
configure_frame_part (struct frame_part *fp)
1351
Lisp_Window *w = fp->win;
1352
XSetWindowAttributes wa;
1356
if (fp->width > 0 && fp->height > 0)
1359
wa.win_gravity = StaticGravity;
1360
wa.bit_gravity = StaticGravity;
1361
wa.colormap = image_cmap;
1362
wa.border_pixel = BlackPixel (dpy, screen_num);
1363
wamask = CWWinGravity | CWBitGravity | CWColormap | CWBorderPixel;
1364
fp->id = XCreateWindow (dpy, w->frame,
1365
fp->x - w->frame_x, fp->y - w->frame_y,
1366
fp->width, fp->height,
1367
0, image_depth, InputOutput,
1368
image_visual, wamask, &wa);
1369
fp->gc = XCreateGC (dpy, fp->id, 0, &gcv);
1370
XSelectInput (dpy, fp->id, FP_EVENTS);
1372
if (!fp->below_client)
1373
XMapRaised (dpy, fp->id);
1376
XMapWindow (dpy, fp->id);
1377
XLowerWindow (dpy, fp->id);
1380
/* stash the fp in the window */
1381
XSaveContext (dpy, fp->id, window_fp_context, (XPointer)fp);
1383
fp->drawn.fg = rep_NULL;
1384
fp->drawn.bg = rep_NULL;
1389
if (fp->width > 0 && fp->height > 0)
1391
XWindowChanges attr;
1392
attr.x = fp->x - w->frame_x;
1393
attr.y = fp->y - w->frame_y;
1394
attr.width = fp->width;
1395
attr.height = fp->height;
1396
attr.stack_mode = fp->below_client ? Below : Above;
1397
XConfigureWindow (dpy, fp->id, CWX | CWY | CWWidth
1398
| CWHeight | CWStackMode, &attr);
1399
/* Generate an Expose event for the window. */
1400
XClearArea (dpy, fp->id, 0, 0, 0, 0, True);
1404
XDestroyWindow (dpy, fp->id);
1406
XFreeGC (dpy, fp->gc);
1412
XDefineCursor (dpy, fp->id, (fp->cursor != Qnil)
1413
? VCURSOR(fp->cursor)->cursor : None);
1417
/* Generate a frame-part frame for window W. If called for a window that
1418
already has a frame, it will be rebuilt to the current window size. */
1420
list_frame_generator (Lisp_Window *w)
1422
repv gen_list = w->frame_style;
1423
repv ptr = rep_NULL, tem;
1424
struct frame_part **last_fp = 0;
1425
struct frame_part *fp = 0;
1426
rep_GC_root gc_win, gc_ptr;
1427
repv win = rep_VAL(w);
1428
bool regen; /* are we resizing the frame */
1431
XSetWindowAttributes wa;
1433
int old_x_off, old_y_off;
1435
/* bounding box of frame */
1436
int left_x, top_y, right_x, bottom_y;
1438
tem = Fwindow_get (rep_VAL(w), Qhide_client);
1439
if (tem && tem != Qnil)
1440
w->client_hidden = 1;
1442
w->client_hidden = 0;
1445
if (!w->client_hidden)
1447
right_x = w->attr.width;
1448
bottom_y = w->attr.height;
1451
right_x = bottom_y = 0;
1453
DB(("list_frame_generator(%s)\n", rep_STR(w->name)));
1455
while (gen_list != Qnil && rep_SYMBOLP(gen_list) && !rep_INTERRUPTP)
1457
gen_list = Fsymbol_value (gen_list, Qt);
1461
rep_PUSHGC(gc_win, win);
1463
/* construct the component list, and find the bounding box */
1465
/* if w->destroy_frame is set then we're rebuilding an existing
1467
if (w->destroy_frame == 0)
1470
last_fp = &w->frame_parts;
1471
assert (w->frame_parts == 0);
1476
fp = w->frame_parts;
1480
/* This loop is a bit weird. If we're building the frame from scratch
1481
we loop over the Lisp list of frame part specs. Otherwise we loop
1482
over the _actual_ list of frame parts */
1483
rep_PUSHGC(gc_ptr, ptr);
1484
while ((!regen && rep_CONSP(ptr))
1485
|| (regen && fp != 0))
1490
fp = fp_new (w, rep_CAR (ptr));
1493
rep_PUSHGC(gc_fp, fp_);
1494
if (build_frame_part (fp))
1496
/* expand frame bounding box */
1497
left_x = MIN(left_x, fp->x);
1498
right_x = MAX(right_x, fp->x + fp->width);
1499
top_y = MIN(top_y, fp->y);
1500
bottom_y = MAX(bottom_y, fp->y + fp->height);
1506
last_fp = &fp->next;
1518
rep_POPGC; /* ptr */
1520
bigger = (right_x - left_x > w->frame_width
1521
|| bottom_y - top_y > w->frame_height);
1523
old_x_off = w->frame_x;
1524
old_y_off = w->frame_y;
1526
/* now we can find the size and offset of the frame. */
1527
w->frame_width = right_x - left_x;
1528
w->frame_height = bottom_y - top_y;
1529
w->frame_x = left_x;
1532
DB((" bounding box: x=%d y=%d width=%d height=%d\n",
1533
left_x, top_y, w->frame_width, w->frame_height));
1535
if (w->reparented && bigger)
1536
set_frame_shapes (w, TRUE);
1538
/* create the child-of-root frame window, or if it already exists,
1539
configure it to the correct size.. */
1542
/* create the frame */
1543
wa.override_redirect = True;
1544
wa.colormap = image_cmap;
1545
wa.border_pixel = BlackPixel (dpy, screen_num);
1546
wamask = CWOverrideRedirect | CWColormap | CWBorderPixel;
1547
w->frame = XCreateWindow (dpy, root_window, w->attr.x, w->attr.y,
1548
w->frame_width, w->frame_height,
1549
0, image_depth, InputOutput,
1550
image_visual, wamask, &wa);
1554
/* adjust frame position to keep absolute client position constant */
1555
w->attr.x += w->frame_x - old_x_off;
1556
w->attr.y += w->frame_y - old_y_off;
1558
XMoveResizeWindow (dpy, w->frame, w->attr.x, w->attr.y,
1559
w->frame_width, w->frame_height);
1562
XMoveResizeWindow (dpy, w->id, -left_x, -top_y,
1563
w->attr.width, w->attr.height);
1565
XResizeWindow (dpy, w->id, w->attr.width, w->attr.height);
1568
w->destroy_frame = frame_part_destroyer;
1569
w->focus_change = refresh_frame_parts;
1570
w->rebuild_frame = list_frame_generator;
1571
w->property_change = refresh_frame_parts;
1574
XLowerWindow (dpy, w->id);
1576
/* create/update windows for each part */
1577
for (fp = w->frame_parts; fp != 0; fp = fp->next)
1578
configure_frame_part (fp);
1580
if (!w->reparented || !bigger)
1581
set_frame_shapes (w, TRUE);
1583
/* ICCCM says we must unmap the client window when it's hidden */
1585
int unmap_client = (!w->visible || w->client_hidden);
1586
if (w->client_unmapped != unmap_client)
1588
before_local_map (w);
1590
XUnmapWindow (dpy, w->id);
1592
XMapWindow (dpy, w->id);
1593
w->client_unmapped = unmap_client;
1594
after_local_map (w);
1595
if (focus_window == w)
1596
focus_on_window (w);
1600
rep_POPGC; /* win */
1603
/* Return the keymap associated with this frame part, or nil */
1605
get_keymap_for_frame_part (struct frame_part *fp)
1607
repv tem = x_fp_assq (fp, Qkeymap);
1613
/* Mark all frame-parts of window W for gc. */
1615
mark_frame_parts (Lisp_Window *w)
1617
struct frame_part *fp;
1618
for (fp = w->frame_parts; fp != 0; fp = fp->next)
1619
rep_MARKVAL (rep_VAL(fp));
1622
/* Reset state of all frame parts in window W. */
1624
reset_frame_parts (Lisp_Window *w)
1626
struct frame_part *fp;
1627
for (fp = w->frame_parts; fp != 0; fp = fp->next)
1629
int old_state = current_state (fp), new_state;
1631
unclick_current_fp ();
1632
fp->highlighted = 0;
1633
new_state = current_state (fp);
1634
if (new_state != old_state)
1635
refresh_frame_part (fp);
1639
/* Make sure stacking in frame is as desired after reparenting
1640
the client into the frame */
1642
restack_frame_parts (Lisp_Window *w)
1644
struct frame_part *fp;
1645
XLowerWindow (dpy, w->id);
1646
for (fp = w->frame_parts; fp != 0; fp = fp->next)
1648
if (fp->id != 0 && fp->below_client)
1649
XLowerWindow (dpy, fp->id);
1654
/* creating window frames */
1656
/* Create a frame for window W. Called with the server grabbed. If
1657
w->frame is non-zero, then we'll use this window to construct the
1658
frame in, otherwise w->frame will be initialised with a new window */
1660
create_window_frame (Lisp_Window *w)
1662
DB(("create_window_frame (%s)\n", rep_STR(w->name)));
1663
if (w->frame_parts == 0)
1665
w->destroy_frame = 0;
1666
w->focus_change = 0;
1667
w->rebuild_frame = 0;
1668
w->property_change = 0;
1669
list_frame_generator (w);
1672
fprintf (stderr, "warning: reframing framed window: %lx\n", (long) w->id);
1675
/* Destroy the frame of window W. If LEAVE-FRAME-WIN is non-zero, then
1676
w->frame won't be destroyed */
1678
destroy_window_frame (Lisp_Window *w, bool leave_frame_win)
1682
if (w->destroy_frame != 0)
1684
w->destroy_frame (w);
1685
w->destroy_frame = 0;
1687
if (!leave_frame_win && w->frame != 0)
1689
XDestroyWindow (dpy, w->frame);
1696
/* Lisp functions */
1698
DEFUN("frame-draw-mutex", Fframe_draw_mutex,
1699
Sframe_draw_mutex, (repv arg), rep_Subr1) /*
1700
::doc:sawfish.wm.frames.subrs#frame-draw-mutex::
1701
While this variable is non-nil no frame parts will be redrawn. When it is
1702
set to nil any pending redraws will take place.
1705
repv ret = frame_draw_mutex ? Qt : Qnil;
1706
frame_draw_mutex = (arg != Qnil);
1707
if (!frame_draw_mutex)
1710
for (w = window_list; w != 0; w = w->next)
1712
struct frame_part *fp;
1713
for (fp = w->frame_parts; fp != 0; fp = fp->next)
1715
if (fp->pending_refresh)
1716
refresh_frame_part (fp);
1723
DEFUN("frame-state-mutex", Fframe_state_mutex,
1724
Sframe_state_mutex, (repv arg), rep_Subr1) /*
1725
::doc:sawfish.wm.frames.subrs#frame-state-mutex::
1726
While this variable is non-nil the state of frame parts will not be
1727
altered when the pointer enters or leaves its window.
1730
repv ret = frame_state_mutex ? Qt : Qnil;
1731
frame_state_mutex = (arg != Qnil);
1733
&& clicked_frame_part != 0
1734
&& !clicked_frame_part->clicked)
1736
/* XXX hack alert */
1737
clicked_frame_part->clicked = 1;
1738
refresh_frame_part (clicked_frame_part);
1743
DEFUN("frame-part-get", Fframe_part_get,
1744
Sframe_part_get, (repv part, repv prop), rep_Subr2) /*
1745
::doc:sawfish.wm.frames.subrs#frame-part-get::
1746
frame-part-get PART PROPERTY
1750
rep_DECLARE1 (part, PARTP);
1751
rep_DECLARE2 (prop, rep_SYMBOLP);
1752
tem = x_fp_assq (VPART(part), prop);
1753
return (tem != Qnil) ? rep_CDR(tem) : Qnil;
1756
DEFUN("frame-part-put", Fframe_part_put, Sframe_part_put,
1757
(repv part, repv prop, repv value), rep_Subr3)
1760
rep_DECLARE1(part, PARTP);
1761
rep_DECLARE2(prop, rep_SYMBOLP);
1762
tem = Fassq (prop, VPART(part)->local_alist);
1763
if (tem != rep_NULL)
1766
rep_CDR (tem) = value;
1768
VPART(part)->local_alist = Fcons (Fcons (prop, value),
1769
VPART(part)->local_alist);
1774
DEFUN("frame-part-window", Fframe_part_window,
1775
Sframe_part_window, (repv part), rep_Subr1)
1777
rep_DECLARE1(part, PARTP);
1778
return rep_VAL(VPART(part)->win);
1781
DEFUN("frame-part-x-window", Fframe_part_x_window,
1782
Sframe_part_x_window, (repv part), rep_Subr1)
1784
rep_DECLARE1(part, PARTP);
1785
return VPART(part)->id != 0 ? rep_MAKE_INT(VPART(part)->id) : Qnil;
1788
DEFUN("frame-part-position", Fframe_part_position,
1789
Sframe_part_position, (repv part), rep_Subr1)
1791
rep_DECLARE1(part, PARTP);
1792
return Fcons (rep_MAKE_INT(VPART(part)->x - VPART(part)->win->frame_x),
1793
rep_MAKE_INT(VPART(part)->y - VPART(part)->win->frame_y));
1796
DEFUN("frame-part-dimensions", Fframe_part_dimensions,
1797
Sframe_part_dimensions, (repv part), rep_Subr1)
1799
rep_DECLARE1(part, PARTP);
1800
return Fcons (rep_MAKE_INT(VPART(part)->width),
1801
rep_MAKE_INT(VPART(part)->height));
1804
DEFUN("frame-part-state", Fframe_part_state,
1805
Sframe_part_state, (repv part), rep_Subr1)
1807
rep_DECLARE1(part, PARTP);
1808
return state_syms[current_state (VPART(part))];
1811
DEFUN("map-frame-parts", Fmap_frame_parts,
1812
Smap_frame_parts, (repv fun, repv win), rep_Subr2)
1815
struct frame_part *fp;
1817
rep_DECLARE (1, fun, Ffunctionp (fun) != Qnil);
1818
rep_DECLARE2 (win, WINDOWP);
1820
rep_PUSHGC (gc_win, win);
1821
fp = VWIN(win)->frame_parts;
1824
repv tem = rep_call_lisp1 (fun, rep_VAL(fp)); /* fun,fp protected */
1825
if (tem == rep_NULL)
1833
DEFUN("refresh-frame-part", Frefresh_frame_part,
1834
Srefresh_frame_part, (repv part), rep_Subr1)
1836
rep_DECLARE1(part, PARTP);
1837
if (VPART(part)->id != 0)
1838
refresh_frame_part (VPART(part));
1842
DEFUN("rebuild-frame-part", Frebuild_frame_part,
1843
Srebuild_frame_part, (repv part), rep_Subr1)
1845
rep_GC_root gc_part;
1846
rep_DECLARE1(part, PARTP);
1847
rep_PUSHGC(gc_part, part);
1848
if (build_frame_part (VPART(part)))
1850
/* XXX what about reconfiguring the container window..? */
1851
configure_frame_part (VPART(part));
1852
queue_reshape_frame (VPART(part)->win);
1858
DEFUN("refresh-window", Frefresh_window,
1859
Srefresh_window, (repv win), rep_Subr1)
1861
rep_DECLARE1(win, XWINDOWP);
1862
if (!WINDOW_IS_GONE_P (VWIN(win)))
1863
refresh_frame_parts (VWIN(win));
1868
/* initialisation */
1874
frame_part_type = rep_register_new_type ("frame-part", fp_cmp, fp_prin,
1875
fp_prin, fp_sweep, fp_mark, 0,
1878
tem = rep_push_structure ("sawfish.wm.frames.subrs");
1879
rep_ADD_SUBR(Sframe_draw_mutex);
1880
rep_ADD_SUBR(Sframe_state_mutex);
1881
rep_ADD_SUBR(Sframe_part_get);
1882
rep_ADD_SUBR(Sframe_part_put);
1883
rep_ADD_SUBR(Sframe_part_window);
1884
rep_ADD_SUBR(Sframe_part_x_window);
1885
rep_ADD_SUBR(Sframe_part_position);
1886
rep_ADD_SUBR(Sframe_part_dimensions);
1887
rep_ADD_SUBR(Sframe_part_state);
1888
rep_ADD_SUBR(Smap_frame_parts);
1889
rep_ADD_SUBR(Srefresh_frame_part);
1890
rep_ADD_SUBR(Srebuild_frame_part);
1891
rep_pop_structure (tem);
1893
tem = rep_push_structure ("sawfish.wm.windows.subrs");
1894
rep_ADD_SUBR(Srefresh_window);
1895
rep_pop_structure (tem);
1897
rep_INTERN(internal);
1905
rep_INTERN(x_justify);
1906
rep_INTERN(y_justify);
1907
rep_INTERN(background);
1908
rep_INTERN(foreground);
1909
rep_INTERN(renderer);
1910
rep_INTERN(render_scale);
1914
rep_INTERN(left_edge);
1915
rep_INTERN(top_edge);
1916
rep_INTERN(right_edge);
1917
rep_INTERN(bottom_edge);
1919
rep_INTERN(focused);
1920
rep_INTERN(highlighted);
1921
rep_INTERN(clicked);
1922
rep_INTERN(inactive);
1923
rep_INTERN(inactive_highlighted);
1924
rep_INTERN(inactive_clicked);
1925
rep_INTERN(hide_client);
1927
rep_INTERN(removable);
1928
rep_INTERN(removed_classes);
1929
rep_INTERN(below_client);
1930
rep_INTERN(scale_foreground);
1933
rep_INTERN_SPECIAL(frame_part_classes);
1934
rep_INTERN_SPECIAL(override_frame_part_classes);
1936
state_syms[fps_inactive] = Qnil;
1937
state_syms[fps_focused] = Qfocused;
1938
state_syms[fps_highlighted] = Qhighlighted;
1939
state_syms[fps_clicked] = Qclicked;
1940
state_syms[fps_inactive_highlighted] = Qinactive_highlighted;
1941
state_syms[fps_inactive_clicked] = Qinactive_clicked;
1943
if (!batch_mode_p ())
1944
window_fp_context = XUniqueContext ();