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"
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, GtkAllocation *allocaction);
27 static void gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area);
28 static void gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area);
29 static void gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition);
30 static void gtk_xemacs_realize (GtkWidget *widget);
31 static void gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style);
32 static gint gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event);
35 gtk_xemacs_get_type (void)
37 static guint xemacs_type = 0;
41 static const GtkTypeInfo xemacs_info =
45 sizeof (GtkXEmacsClass),
46 (GtkClassInitFunc) gtk_xemacs_class_init,
47 (GtkObjectInitFunc) gtk_xemacs_init,
48 /* reserved_1 */ NULL,
49 /* reserved_2 */ NULL,
50 (GtkClassInitFunc) NULL,
53 xemacs_type = gtk_type_unique (gtk_fixed_get_type (), &xemacs_info);
59 static GtkWidgetClass *parent_class;
61 extern gint emacs_gtk_button_event_handler(GtkWidget *widget, GdkEventButton *event);
62 extern gint emacs_gtk_key_event_handler(GtkWidget *widget, GdkEventKey *event);
63 extern gint emacs_gtk_motion_event_handler(GtkWidget *widget, GdkEventMotion *event);
66 gtk_xemacs_class_init (GtkXEmacsClass *class)
68 GtkWidgetClass *widget_class;
70 widget_class = (GtkWidgetClass*) class;
71 parent_class = (GtkWidgetClass *) gtk_type_class (gtk_fixed_get_type ());
73 widget_class->size_allocate = gtk_xemacs_size_allocate;
74 widget_class->size_request = gtk_xemacs_size_request;
75 widget_class->draw = gtk_xemacs_draw;
76 widget_class->expose_event = gtk_xemacs_expose;
77 widget_class->realize = gtk_xemacs_realize;
78 widget_class->button_press_event = emacs_gtk_button_event_handler;
79 widget_class->button_release_event = emacs_gtk_button_event_handler;
80 widget_class->key_press_event = emacs_gtk_key_event_handler;
81 widget_class->key_release_event = emacs_gtk_key_event_handler;
82 widget_class->motion_notify_event = emacs_gtk_motion_event_handler;
83 widget_class->style_set = gtk_xemacs_style_set;
87 gtk_xemacs_init (GtkXEmacs *xemacs)
89 GTK_WIDGET_SET_FLAGS (xemacs, GTK_CAN_FOCUS);
93 gtk_xemacs_new (struct frame *f)
97 xemacs = gtk_type_new (gtk_xemacs_get_type ());
100 return GTK_WIDGET (xemacs);
104 __nuke_background_items (GtkWidget *widget)
106 /* This bit of voodoo is here to get around the annoying flicker
107 when GDK tries to futz with our background pixmap as well as
110 We do NOT set the background of this widget window, that way
111 there is NO flickering, etc. The downside is the XEmacs frame
112 appears as 'seethru' when XEmacs is too busy to redraw the
115 Well, wait, we do... otherwise there sre weird 'seethru' areas
116 even when XEmacs does a full redisplay. Most noticable in some
117 areas of the modeline, or in the right-hand-side of the window
118 between the scrollbar ad n the edge of the window.
122 gdk_window_set_back_pixmap (widget->window, NULL, 0);
123 gdk_window_set_back_pixmap (widget->parent->window, NULL, 0);
124 gdk_window_set_background (widget->parent->window,
125 &widget->style->bg[GTK_STATE_NORMAL]);
126 gdk_window_set_background (widget->window,
127 &widget->style->bg[GTK_STATE_NORMAL]);
131 extern Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w);
133 /* From objects-gtk.c */
134 extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp);
136 #define convert_font(f) __get_gtk_font_truename (f, 0)
139 smash_face_fallbacks (struct frame *f, GtkStyle *style)
141 #define FROB(face,prop,slot) do { \
142 Lisp_Object fallback = Qnil; \
143 Lisp_Object specifier = Fget (face, prop, Qnil); \
144 struct Lisp_Specifier *sp = NULL; \
145 if (NILP (specifier)) continue; \
146 sp = XSPECIFIER (specifier); \
147 fallback = sp->fallback; \
148 if (EQ (Fcar (Fcar (Fcar (fallback))), Qgtk)) \
149 fallback = XCDR (fallback); \
151 fallback = acons (list1 (Qgtk), \
154 set_specifier_fallback (specifier, fallback); \
156 #define FROB_FACE(face,fg_slot,bg_slot) \
158 FROB (face, Qforeground, xemacs_gtk_convert_color (&style->fg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \
159 FROB (face, Qbackground, xemacs_gtk_convert_color (&style->bg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \
160 if (style->rc_style && style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]) \
162 FROB (Vdefault_face, Qbackground_pixmap, \
163 Fmake_image_instance (build_string (style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]), \
164 f->device, Qnil, make_int (5))); \
168 FROB (Vdefault_face, Qbackground_pixmap, Qnil); \
172 FROB (Vdefault_face, Qfont, convert_font (style->font));
173 FROB_FACE (Vdefault_face, fg, bg);
174 FROB_FACE (Vgui_element_face, text, mid);
180 #ifdef HAVE_SCROLLBARS
182 smash_scrollbar_specifiers (struct frame *f, GtkStyle *style)
187 GtkRangeClass *klass;
189 XSETFRAME (frame, f);
191 klass = (GtkRangeClass *) gtk_type_class (GTK_TYPE_SCROLLBAR);
192 slider_size = klass->slider_width;
193 hsize = slider_size + (style->klass->ythickness * 2);
194 vsize = slider_size + (style->klass->xthickness * 2);
196 style = gtk_style_attach (style,
197 GTK_WIDGET (DEVICE_GTK_APP_SHELL (XDEVICE (FRAME_DEVICE (f))))->window);
199 Fadd_spec_to_specifier (Vscrollbar_width, make_int (vsize), frame, Qnil, Qnil);
200 Fadd_spec_to_specifier (Vscrollbar_height, make_int (hsize), frame, Qnil, Qnil);
203 #define smash_scrollbar_specifiers(x,y)
204 #endif /* HAVE_SCROLLBARS */
207 gtk_xemacs_realize (GtkWidget *widget)
209 parent_class->realize (widget);
210 gtk_xemacs_style_set (widget, gtk_widget_get_style (widget));
214 gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style)
216 GtkStyle *new_style = gtk_widget_get_style (widget);
217 GtkXEmacs *x = GTK_XEMACS (widget);
219 parent_class->style_set (widget, previous_style);
223 __nuke_background_items (widget);
225 smash_face_fallbacks (x->f, new_style);
227 smash_scrollbar_specifiers (x->f, new_style);
232 gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition)
234 GtkXEmacs *x = GTK_XEMACS (widget);
235 struct frame *f = GTK_XEMACS_FRAME (x);
240 char_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f),
242 requisition->width = width;
243 requisition->height = height;
247 parent_class->size_request (widget, requisition);
251 /* Assign a size and position to the child widgets. This differs from the
252 super class method in that for all widgets except the scrollbars the size
253 and position are not caclulated here. This is because these widgets have
254 this function performed for them by the redisplay code (see
255 gtk_map_subwindow()). If the superclass method is called then the widgets
256 can change size and position as the two pieces of code move the widgets at
260 gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
262 GtkXEmacs *x = GTK_XEMACS (widget);
263 GtkFixed *fixed = GTK_FIXED (widget);
264 struct frame *f = GTK_XEMACS_FRAME (x);
267 guint16 border_width;
269 widget->allocation = *allocation;
270 if (GTK_WIDGET_REALIZED (widget))
271 gdk_window_move_resize (widget->window,
277 border_width = GTK_CONTAINER (fixed)->border_width;
279 children = fixed->children;
282 GtkFixedChild* child = children->data;
283 children = children->next;
286 Scrollbars are the only widget that is managed by GTK. See
287 comments in gtk_create_scrollbar_instance().
289 if (GTK_WIDGET_VISIBLE (child->widget) &&
290 gtk_type_is_a(GTK_OBJECT_TYPE(child->widget), GTK_TYPE_SCROLLBAR))
292 GtkAllocation child_allocation;
293 GtkRequisition child_requisition;
295 gtk_widget_get_child_requisition (child->widget, &child_requisition);
296 child_allocation.x = child->x + border_width;
297 child_allocation.y = child->y + border_width;
298 child_allocation.width = child_requisition.width;
299 child_allocation.height = child_requisition.height;
300 gtk_widget_size_allocate (child->widget, &child_allocation);
306 f->pixwidth = allocation->width;
307 f->pixheight = allocation->height;
309 pixel_to_char_size (f,
311 allocation->height, &columns, &rows);
313 change_frame_size (f, rows, columns, 1);
318 gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area)
320 GtkXEmacs *x = GTK_XEMACS (widget);
321 struct frame *f = GTK_XEMACS_FRAME (x);
323 if (GTK_WIDGET_DRAWABLE (widget))
324 gtk_redraw_exposed_area (f, area->x, area->y, area->width, area->height);
328 gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area)
330 GtkFixed *fixed = GTK_FIXED (widget);
331 GtkFixedChild *child;
332 GdkRectangle child_area;
335 /* I need to manually iterate over the children instead of just
336 chaining to parent_class->draw() because it calls
337 gtk_fixed_paint() directly, which clears the background window,
338 which causes A LOT of flashing. */
340 if (GTK_WIDGET_DRAWABLE (widget))
342 gtk_xemacs_paint (widget, area);
344 children = fixed->children;
348 child = children->data;
349 children = children->next;
350 /* #### This is what causes the scrollbar flickering!
351 Evidently the scrollbars pretty much take care of drawing
352 themselves in most cases. Then we come along and tell them
355 But if we just leave it out, then they do not get drawn
356 correctly the first time!
358 Scrollbar flickering has been greatly helped by the
359 optimizations in scrollbar-gtk.c /
360 gtk_update_scrollbar_instance_status (), so this is not that
363 if (gtk_widget_intersect (child->widget, area, &child_area))
365 gtk_widget_draw (child->widget, &child_area);
372 gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event)
374 GtkXEmacs *x = GTK_XEMACS (widget);
375 struct frame *f = GTK_XEMACS_FRAME (x);
376 GdkRectangle *a = &event->area;
378 if (GTK_WIDGET_DRAWABLE (widget))
380 /* This takes care of drawing the scrollbars, etc */
381 parent_class->expose_event (widget, event);
383 /* Now draw the actual frame data */
384 if (!check_for_ignored_expose (f, a->x, a->y, a->width, a->height) &&
385 !find_matching_subwindow (f, a->x, a->y, a->width, a->height))
386 gtk_redraw_exposed_area (f, a->x, a->y, a->width, a->height);
394 xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w)
398 sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue);
400 return (build_string (color_buf));