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);
252 gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
254 GtkXEmacs *x = GTK_XEMACS (widget);
255 struct frame *f = GTK_XEMACS_FRAME (x);
258 parent_class->size_allocate(widget, allocation);
262 f->pixwidth = allocation->width;
263 f->pixheight = allocation->height;
265 pixel_to_char_size (f,
267 allocation->height, &columns, &rows);
269 change_frame_size (f, rows, columns, 1);
274 gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area)
276 GtkXEmacs *x = GTK_XEMACS (widget);
277 struct frame *f = GTK_XEMACS_FRAME (x);
278 gtk_redraw_exposed_area (f, area->x, area->y, area->width, area->height);
282 gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area)
284 GtkFixed *fixed = GTK_FIXED (widget);
285 GtkFixedChild *child;
286 GdkRectangle child_area;
289 /* I need to manually iterate over the children instead of just
290 chaining to parent_class->draw() because it calls
291 gtk_fixed_paint() directly, which clears the background window,
292 which causes A LOT of flashing. */
294 gtk_xemacs_paint (widget, area);
296 children = fixed->children;
300 child = children->data;
301 children = children->next;
302 /* #### This is what causes the scrollbar flickering!
303 Evidently the scrollbars pretty much take care of drawing
304 themselves in most cases. Then we come along and tell them
307 But if we just leave it out, then they do not get drawn
308 correctly the first time!
310 Scrollbar flickering has been greatly helped by the
311 optimizations in scrollbar-gtk.c /
312 gtk_update_scrollbar_instance_status (), so this is not that
315 if (gtk_widget_intersect (child->widget, area, &child_area))
317 gtk_widget_draw (child->widget, &child_area);
323 gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event)
325 GtkXEmacs *x = GTK_XEMACS (widget);
326 struct frame *f = GTK_XEMACS_FRAME (x);
327 GdkRectangle *a = &event->area;
329 /* This takes care of drawing the scrollbars, etc */
330 parent_class->expose_event (widget, event);
332 /* Now draw the actual frame data */
333 if (!check_for_ignored_expose (f, a->x, a->y, a->width, a->height) &&
334 !find_matching_subwindow (f, a->x, a->y, a->width, a->height))
335 gtk_redraw_exposed_area (f, a->x, a->y, a->width, a->height);
340 xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w)
344 sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue);
346 return (build_string (color_buf));