Mercurial > hg > xemacs-beta
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 } |