3 ** Description: A widget to encapsulate a XEmacs 'text widget'
5 ** Created by: William M. Perry
6 ** Copyright (c) 2000 William M. Perry <wmperry@gnu.org>
13 #include "console-gtk.h"
14 #include "objects-gtk.h"
15 #include "gtk-xemacs.h"
16 #include "ui/window.h"
19 extern Lisp_Object Vmodeline_face;
20 extern Lisp_Object Vscrollbar_on_left_p;
22 EXFUN(Fmake_image_instance, 4);
24 static void gtk_xemacs_class_init(GtkXEmacsClass * klass);
25 static void gtk_xemacs_init(GtkXEmacs * xemacs);
26 static void gtk_xemacs_size_allocate(GtkWidget * widget,
27 GtkAllocation * allocaction);
28 static void gtk_xemacs_draw(GtkWidget * widget, GdkRectangle * area);
29 static void gtk_xemacs_paint(GtkWidget * widget, GdkRectangle * area);
30 static void gtk_xemacs_size_request(GtkWidget * widget,
31 GtkRequisition * requisition);
32 static void gtk_xemacs_realize(GtkWidget * widget);
33 static void gtk_xemacs_style_set(GtkWidget * widget, GtkStyle * previous_style);
34 static gint gtk_xemacs_expose(GtkWidget * widget, GdkEventExpose * event);
36 guint gtk_xemacs_get_type(void)
38 static guint xemacs_type = 0;
41 static const GtkTypeInfo xemacs_info = {
44 sizeof(GtkXEmacsClass),
45 (GtkClassInitFunc) gtk_xemacs_class_init,
46 (GtkObjectInitFunc) gtk_xemacs_init,
47 /* reserved_1 */ NULL,
48 /* reserved_2 */ NULL,
49 (GtkClassInitFunc) NULL,
53 gtk_type_unique(gtk_fixed_get_type(), &xemacs_info);
59 static GtkWidgetClass *parent_class;
61 extern gint emacs_gtk_button_event_handler(GtkWidget * widget,
62 GdkEventButton * event);
63 extern gint emacs_gtk_key_event_handler(GtkWidget * widget,
65 extern gint emacs_gtk_motion_event_handler(GtkWidget * widget,
66 GdkEventMotion * event);
68 static void gtk_xemacs_class_init(GtkXEmacsClass * class)
70 GtkWidgetClass *widget_class;
72 widget_class = (GtkWidgetClass *) class;
73 parent_class = (GtkWidgetClass *) gtk_type_class(gtk_fixed_get_type());
75 widget_class->size_allocate = gtk_xemacs_size_allocate;
76 widget_class->size_request = gtk_xemacs_size_request;
77 widget_class->draw = gtk_xemacs_draw;
78 widget_class->expose_event = gtk_xemacs_expose;
79 widget_class->realize = gtk_xemacs_realize;
80 widget_class->button_press_event = emacs_gtk_button_event_handler;
81 widget_class->button_release_event = emacs_gtk_button_event_handler;
82 widget_class->key_press_event = emacs_gtk_key_event_handler;
83 widget_class->key_release_event = emacs_gtk_key_event_handler;
84 widget_class->motion_notify_event = emacs_gtk_motion_event_handler;
85 widget_class->style_set = gtk_xemacs_style_set;
88 static void gtk_xemacs_init(GtkXEmacs * xemacs)
90 GTK_WIDGET_SET_FLAGS(xemacs, GTK_CAN_FOCUS);
93 GtkWidget *gtk_xemacs_new(struct frame *f)
97 xemacs = gtk_type_new(gtk_xemacs_get_type());
100 return GTK_WIDGET(xemacs);
103 static void __nuke_background_items(GtkWidget * widget)
105 /* This bit of voodoo is here to get around the annoying flicker
106 when GDK tries to futz with our background pixmap as well as
109 We do NOT set the background of this widget window, that way
110 there is NO flickering, etc. The downside is the XEmacs frame
111 appears as 'seethru' when XEmacs is too busy to redraw the
114 Well, wait, we do... otherwise there sre weird 'seethru' areas
115 even when XEmacs does a full redisplay. Most noticable in some
116 areas of the modeline, or in the right-hand-side of the window
117 between the scrollbar ad n the edge of the window.
119 if (widget->window) {
120 gdk_window_set_back_pixmap(widget->window, NULL, 0);
121 gdk_window_set_back_pixmap(widget->parent->window, NULL, 0);
122 gdk_window_set_background(widget->parent->window,
123 &widget->style->bg[GTK_STATE_NORMAL]);
124 gdk_window_set_background(widget->window,
125 &widget->style->bg[GTK_STATE_NORMAL]);
129 extern Lisp_Object xemacs_gtk_convert_color(GdkColor * c, GtkWidget * w);
131 /* From objects-gtk.c */
132 extern Lisp_Object __get_gtk_font_truename(GdkFont * gdk_font, int expandp);
134 #define convert_font(f) __get_gtk_font_truename (f, 0)
136 static void smash_face_fallbacks(struct frame *f, GtkStyle * style)
138 #define FROB(face,prop,slot) do { \
139 Lisp_Object fallback = Qnil; \
140 Lisp_Object specifier = Fget (face, prop, Qnil); \
141 struct Lisp_Specifier *sp = NULL; \
142 if (NILP (specifier)) continue; \
143 sp = XSPECIFIER (specifier); \
144 fallback = sp->fallback; \
145 if (EQ (Fcar (Fcar (Fcar (fallback))), Qgtk)) \
146 fallback = XCDR (fallback); \
148 fallback = acons (list1 (Qgtk), \
151 set_specifier_fallback (specifier, fallback); \
153 #define FROB_FACE(face,fg_slot,bg_slot) \
155 FROB (face, Qforeground, xemacs_gtk_convert_color (&style->fg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \
156 FROB (face, Qbackground, xemacs_gtk_convert_color (&style->bg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \
157 if (style->rc_style && style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]) \
159 FROB (Vdefault_face, Qbackground_pixmap, \
160 Fmake_image_instance (build_string (style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]), \
161 f->device, Qnil, make_int (5))); \
165 FROB (Vdefault_face, Qbackground_pixmap, Qnil); \
169 FROB(Vdefault_face, Qfont, convert_font(style->font));
170 FROB_FACE(Vdefault_face, fg, bg);
171 FROB_FACE(Vgui_element_face, text, mid);
177 #ifdef HAVE_SCROLLBARS
178 static void smash_scrollbar_specifiers(struct frame *f, GtkStyle * style)
183 GtkRangeClass *klass;
187 klass = (GtkRangeClass *) gtk_type_class(GTK_TYPE_SCROLLBAR);
188 slider_size = klass->slider_width;
189 hsize = slider_size + (style->klass->ythickness * 2);
190 vsize = slider_size + (style->klass->xthickness * 2);
192 style = gtk_style_attach(style,
193 GTK_WIDGET(DEVICE_GTK_APP_SHELL
194 (XDEVICE(FRAME_DEVICE(f))))->
197 Fadd_spec_to_specifier(Vscrollbar_width, make_int(vsize), frame, Qnil,
199 Fadd_spec_to_specifier(Vscrollbar_height, make_int(hsize), frame, Qnil,
203 #define smash_scrollbar_specifiers(x,y)
204 #endif /* HAVE_SCROLLBARS */
206 static void gtk_xemacs_realize(GtkWidget * widget)
208 parent_class->realize(widget);
209 gtk_xemacs_style_set(widget, gtk_widget_get_style(widget));
212 static void gtk_xemacs_style_set(GtkWidget * widget, GtkStyle * previous_style)
214 GtkStyle *new_style = gtk_widget_get_style(widget);
215 GtkXEmacs *x = GTK_XEMACS(widget);
217 parent_class->style_set(widget, previous_style);
220 __nuke_background_items(widget);
222 smash_face_fallbacks(x->f, new_style);
224 smash_scrollbar_specifiers(x->f, new_style);
229 gtk_xemacs_size_request(GtkWidget * widget, GtkRequisition * requisition)
231 GtkXEmacs *x = GTK_XEMACS(widget);
232 struct frame *f = GTK_XEMACS_FRAME(x);
236 char_to_pixel_size(f, FRAME_WIDTH(f), FRAME_HEIGHT(f),
238 requisition->width = width;
239 requisition->height = height;
241 parent_class->size_request(widget, requisition);
245 /* Assign a size and position to the child widgets. This differs from the
246 super class method in that for all widgets except the scrollbars the size
247 and position are not caclulated here. This is because these widgets have
248 this function performed for them by the redisplay code (see
249 gtk_map_subwindow()). If the superclass method is called then the widgets
250 can change size and position as the two pieces of code move the widgets at
254 gtk_xemacs_size_allocate(GtkWidget * widget, GtkAllocation * allocation)
256 GtkXEmacs *x = GTK_XEMACS(widget);
257 GtkFixed *fixed = GTK_FIXED(widget);
258 struct frame *f = GTK_XEMACS_FRAME(x);
261 guint16 border_width;
263 widget->allocation = *allocation;
264 if (GTK_WIDGET_REALIZED(widget))
265 gdk_window_move_resize(widget->window,
268 allocation->width, allocation->height);
270 border_width = GTK_CONTAINER(fixed)->border_width;
272 children = fixed->children;
274 GtkFixedChild *child = children->data;
275 children = children->next;
278 Scrollbars are the only widget that is managed by GTK. See
279 comments in gtk_create_scrollbar_instance().
281 if (GTK_WIDGET_VISIBLE(child->widget) &&
282 gtk_type_is_a(GTK_OBJECT_TYPE(child->widget),
283 GTK_TYPE_SCROLLBAR)) {
284 GtkAllocation child_allocation;
285 GtkRequisition child_requisition;
287 gtk_widget_get_child_requisition(child->widget,
289 child_allocation.x = child->x + border_width;
290 child_allocation.y = child->y + border_width;
291 child_allocation.width = child_requisition.width;
292 child_allocation.height = child_requisition.height;
293 gtk_widget_size_allocate(child->widget,
299 f->pixwidth = allocation->width;
300 f->pixheight = allocation->height;
302 pixel_to_char_size(f,
304 allocation->height, &columns, &rows);
306 change_frame_size(f, rows, columns, 1);
310 static void gtk_xemacs_paint(GtkWidget * widget, GdkRectangle * area)
312 GtkXEmacs *x = GTK_XEMACS(widget);
313 struct frame *f = GTK_XEMACS_FRAME(x);
315 if (GTK_WIDGET_DRAWABLE(widget))
316 gtk_redraw_exposed_area(f, area->x, area->y, area->width,
320 static void gtk_xemacs_draw(GtkWidget * widget, GdkRectangle * area)
322 GtkFixed *fixed = GTK_FIXED(widget);
323 GtkFixedChild *child;
324 GdkRectangle child_area;
327 /* I need to manually iterate over the children instead of just
328 chaining to parent_class->draw() because it calls
329 gtk_fixed_paint() directly, which clears the background window,
330 which causes A LOT of flashing. */
332 if (GTK_WIDGET_DRAWABLE(widget)) {
333 gtk_xemacs_paint(widget, area);
335 children = fixed->children;
338 child = children->data;
339 children = children->next;
340 /* #### This is what causes the scrollbar flickering!
341 Evidently the scrollbars pretty much take care of drawing
342 themselves in most cases. Then we come along and tell them
345 But if we just leave it out, then they do not get drawn
346 correctly the first time!
348 Scrollbar flickering has been greatly helped by the
349 optimizations in scrollbar-gtk.c /
350 gtk_update_scrollbar_instance_status (), so this is not that
353 if (gtk_widget_intersect
354 (child->widget, area, &child_area)) {
355 gtk_widget_draw(child->widget, &child_area);
361 static gint gtk_xemacs_expose(GtkWidget * widget, GdkEventExpose * event)
363 GtkXEmacs *x = GTK_XEMACS(widget);
364 struct frame *f = GTK_XEMACS_FRAME(x);
365 GdkRectangle *a = &event->area;
367 if (GTK_WIDGET_DRAWABLE(widget)) {
368 /* This takes care of drawing the scrollbars, etc */
369 parent_class->expose_event(widget, event);
371 /* Now draw the actual frame data */
372 if (!check_for_ignored_expose
373 (f, a->x, a->y, a->width, a->height)
374 && !find_matching_subwindow(f, a->x, a->y, a->width,
376 gtk_redraw_exposed_area(f, a->x, a->y, a->width,
384 Lisp_Object xemacs_gtk_convert_color(GdkColor * c, GtkWidget * w)
388 sprintf(color_buf, "#%04x%04x%04x", c->red, c->green, c->blue);
390 return (build_string(color_buf));