comparison src/gtk-xemacs.c @ 462:0784d089fdc9 r21-2-46

Import from CVS: tag r21-2-46
author cvs
date Mon, 13 Aug 2007 11:44:37 +0200
parents
children 8ae895c67ce7
comparison
equal deleted inserted replaced
461:120ed4009e51 462:0784d089fdc9
1 /* gtk-xemacs.c
2 **
3 ** Description: A widget to encapsulate a XEmacs 'text widget'
4 **
5 ** Created by: William M. Perry
6 ** Copyright (c) 2000 William M. Perry <wmperry@gnu.org>
7 **
8 */
9
10 #include <config.h>
11
12 #include "lisp.h"
13 #include "console-gtk.h"
14 #include "objects-gtk.h"
15 #include "gtk-xemacs.h"
16 #include "window.h"
17 #include "faces.h"
18
19 extern Lisp_Object Vmodeline_face;
20 extern Lisp_Object Vscrollbar_on_left_p;
21
22 EXFUN (Fmake_image_instance, 4);
23
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);
33
34 guint
35 gtk_xemacs_get_type (void)
36 {
37 static guint xemacs_type = 0;
38
39 if (!xemacs_type)
40 {
41 static const GtkTypeInfo xemacs_info =
42 {
43 "GtkXEmacs",
44 sizeof (GtkXEmacs),
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,
51 };
52
53 xemacs_type = gtk_type_unique (gtk_fixed_get_type (), &xemacs_info);
54 }
55
56 return xemacs_type;
57 }
58
59 static GtkWidgetClass *parent_class;
60
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);
64
65 static void
66 gtk_xemacs_class_init (GtkXEmacsClass *class)
67 {
68 GtkWidgetClass *widget_class;
69
70 widget_class = (GtkWidgetClass*) class;
71 parent_class = (GtkWidgetClass *) gtk_type_class (gtk_fixed_get_type ());
72
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;
84 }
85
86 static void
87 gtk_xemacs_init (GtkXEmacs *xemacs)
88 {
89 GTK_WIDGET_SET_FLAGS (xemacs, GTK_CAN_FOCUS);
90 }
91
92 GtkWidget*
93 gtk_xemacs_new (struct frame *f)
94 {
95 GtkXEmacs *xemacs;
96
97 xemacs = gtk_type_new (gtk_xemacs_get_type ());
98 xemacs->f = f;
99
100 return GTK_WIDGET (xemacs);
101 }
102
103 static void
104 __nuke_background_items (GtkWidget *widget)
105 {
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
108 XEmacs doing it
109
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
113 frame.
114
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.
119 */
120 if (widget->window)
121 {
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]);
128 }
129 }
130
131 extern Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w);
132
133 /* From objects-gtk.c */
134 extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp);
135
136 #define convert_font(f) __get_gtk_font_truename (f, 0)
137
138 static void
139 smash_face_fallbacks (struct frame *f, GtkStyle *style)
140 {
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); \
150 if (! NILP (slot)) \
151 fallback = acons (list1 (Qgtk), \
152 slot, \
153 fallback); \
154 set_specifier_fallback (specifier, fallback); \
155 } while (0);
156 #define FROB_FACE(face,fg_slot,bg_slot) \
157 do { \
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]) \
161 { \
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))); \
165 } \
166 else \
167 { \
168 FROB (Vdefault_face, Qbackground_pixmap, Qnil); \
169 } \
170 } while (0)
171
172 FROB (Vdefault_face, Qfont, convert_font (style->font));
173 FROB_FACE (Vdefault_face, fg, bg);
174 FROB_FACE (Vgui_element_face, text, mid);
175
176 #undef FROB
177 #undef FROB_FACE
178 }
179
180 #ifdef HAVE_SCROLLBARS
181 static void
182 smash_scrollbar_specifiers (struct frame *f, GtkStyle *style)
183 {
184 Lisp_Object frame;
185 int slider_size = 0;
186 int hsize, vsize;
187 GtkRangeClass *klass;
188
189 XSETFRAME (frame, f);
190
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);
195
196 style = gtk_style_attach (style,
197 GTK_WIDGET (DEVICE_GTK_APP_SHELL (XDEVICE (FRAME_DEVICE (f))))->window);
198
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);
201 }
202 #else
203 #define smash_scrollbar_specifiers(x,y)
204 #endif /* HAVE_SCROLLBARS */
205
206 static void
207 gtk_xemacs_realize (GtkWidget *widget)
208 {
209 parent_class->realize (widget);
210 gtk_xemacs_style_set (widget, gtk_widget_get_style (widget));
211 }
212
213 static void
214 gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style)
215 {
216 GtkStyle *new_style = gtk_widget_get_style (widget);
217 GtkXEmacs *x = GTK_XEMACS (widget);
218
219 parent_class->style_set (widget, previous_style);
220
221 if (x->f)
222 {
223 __nuke_background_items (widget);
224 #if 0
225 smash_face_fallbacks (x->f, new_style);
226 #endif
227 smash_scrollbar_specifiers (x->f, new_style);
228 }
229 }
230
231 static void
232 gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition)
233 {
234 GtkXEmacs *x = GTK_XEMACS (widget);
235 struct frame *f = GTK_XEMACS_FRAME (x);
236 int width, height;
237
238 if (f)
239 {
240 char_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f),
241 &width, &height);
242 requisition->width = width;
243 requisition->height = height;
244 }
245 else
246 {
247 parent_class->size_request (widget, requisition);
248 }
249 }
250
251 static void
252 gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
253 {
254 GtkXEmacs *x = GTK_XEMACS (widget);
255 struct frame *f = GTK_XEMACS_FRAME (x);
256 int columns, rows;
257
258 parent_class->size_allocate(widget, allocation);
259
260 if (f)
261 {
262 f->pixwidth = allocation->width;
263 f->pixheight = allocation->height;
264
265 pixel_to_char_size (f,
266 allocation->width,
267 allocation->height, &columns, &rows);
268
269 change_frame_size (f, rows, columns, 1);
270 }
271 }
272
273 static void
274 gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area)
275 {
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);
279 }
280
281 static void
282 gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area)
283 {
284 GtkFixed *fixed = GTK_FIXED (widget);
285 GtkFixedChild *child;
286 GdkRectangle child_area;
287 GList *children;
288
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. */
293
294 gtk_xemacs_paint (widget, area);
295
296 children = fixed->children;
297
298 while (children)
299 {
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
305 to redraw again!
306
307 But if we just leave it out, then they do not get drawn
308 correctly the first time!
309
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
313 big a deal anymore.
314 */
315 if (gtk_widget_intersect (child->widget, area, &child_area))
316 {
317 gtk_widget_draw (child->widget, &child_area);
318 }
319 }
320 }
321
322 static gint
323 gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event)
324 {
325 GtkXEmacs *x = GTK_XEMACS (widget);
326 struct frame *f = GTK_XEMACS_FRAME (x);
327 GdkRectangle *a = &event->area;
328
329 /* This takes care of drawing the scrollbars, etc */
330 parent_class->expose_event (widget, event);
331
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);
336 return (TRUE);
337 }
338
339 Lisp_Object
340 xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w)
341 {
342 char color_buf[255];
343
344 sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue);
345
346 return (build_string (color_buf));
347 }