Mercurial > hg > xemacs-beta
annotate src/gtk-xemacs.c @ 4709:db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
are missing. This is done with Bill Perry's stated permission, in private
email to me.
author | Jerry James <james@xemacs.org> |
---|---|
date | Mon, 05 Oct 2009 11:08:59 -0600 |
parents | dbd2a866e38a |
children | b3ce27ca7647 304aebb79cd3 |
rev | line source |
---|---|
462 | 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 ** | |
4709
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
8 ** This file is part of XEmacs. |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
9 ** |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
10 ** XEmacs is free software; you can redistribute it and/or modify it |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
11 ** under the terms of the GNU General Public License as published by the |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
12 ** Free Software Foundation; either version 2, or (at your option) any |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
13 ** later version. |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
14 ** |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
15 ** XEmacs is distributed in the hope that it will be useful, but WITHOUT |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
16 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
17 ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
18 ** for more details. |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
19 ** |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
20 ** You should have received a copy of the GNU General Public License |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
21 ** along with XEmacs; see the file COPYING. If not, write to |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
22 ** the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
23 ** Boston, MA 02111-1301, USA. */ |
462 | 24 */ |
25 | |
26 #include <config.h> | |
27 | |
28 #include "lisp.h" | |
29 #include "console-gtk.h" | |
30 #include "objects-gtk.h" | |
31 #include "gtk-xemacs.h" | |
809 | 32 #include "device.h" |
33 #include "glyphs.h" | |
462 | 34 #include "window.h" |
35 #include "faces.h" | |
778 | 36 #include "event-gtk.h" |
876 | 37 #include "frame-impl.h" |
38 #include "console-gtk-impl.h" | |
39 #include "device-impl.h" | |
462 | 40 |
41 extern Lisp_Object Vmodeline_face; | |
42 extern Lisp_Object Vscrollbar_on_left_p; | |
43 | |
44 EXFUN (Fmake_image_instance, 4); | |
45 | |
46 static void gtk_xemacs_class_init (GtkXEmacsClass *klass); | |
47 static void gtk_xemacs_init (GtkXEmacs *xemacs); | |
48 static void gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocaction); | |
49 static void gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area); | |
50 static void gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area); | |
51 static void gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition); | |
52 static void gtk_xemacs_realize (GtkWidget *widget); | |
53 static void gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style); | |
54 static gint gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event); | |
55 | |
56 guint | |
57 gtk_xemacs_get_type (void) | |
58 { | |
59 static guint xemacs_type = 0; | |
60 | |
61 if (!xemacs_type) | |
62 { | |
63 static const GtkTypeInfo xemacs_info = | |
64 { | |
65 "GtkXEmacs", | |
66 sizeof (GtkXEmacs), | |
67 sizeof (GtkXEmacsClass), | |
68 (GtkClassInitFunc) gtk_xemacs_class_init, | |
69 (GtkObjectInitFunc) gtk_xemacs_init, | |
70 /* reserved_1 */ NULL, | |
71 /* reserved_2 */ NULL, | |
72 (GtkClassInitFunc) NULL, | |
73 }; | |
74 | |
75 xemacs_type = gtk_type_unique (gtk_fixed_get_type (), &xemacs_info); | |
76 } | |
77 | |
78 return xemacs_type; | |
79 } | |
80 | |
81 static GtkWidgetClass *parent_class; | |
82 | |
83 static void | |
1204 | 84 gtk_xemacs_class_init (GtkXEmacsClass *class_) |
462 | 85 { |
86 GtkWidgetClass *widget_class; | |
87 | |
1204 | 88 widget_class = (GtkWidgetClass*) class_; |
462 | 89 parent_class = (GtkWidgetClass *) gtk_type_class (gtk_fixed_get_type ()); |
90 | |
91 widget_class->size_allocate = gtk_xemacs_size_allocate; | |
92 widget_class->size_request = gtk_xemacs_size_request; | |
93 widget_class->draw = gtk_xemacs_draw; | |
94 widget_class->expose_event = gtk_xemacs_expose; | |
95 widget_class->realize = gtk_xemacs_realize; | |
96 widget_class->button_press_event = emacs_gtk_button_event_handler; | |
97 widget_class->button_release_event = emacs_gtk_button_event_handler; | |
98 widget_class->key_press_event = emacs_gtk_key_event_handler; | |
99 widget_class->key_release_event = emacs_gtk_key_event_handler; | |
100 widget_class->motion_notify_event = emacs_gtk_motion_event_handler; | |
101 widget_class->style_set = gtk_xemacs_style_set; | |
102 } | |
103 | |
104 static void | |
105 gtk_xemacs_init (GtkXEmacs *xemacs) | |
106 { | |
107 GTK_WIDGET_SET_FLAGS (xemacs, GTK_CAN_FOCUS); | |
108 } | |
109 | |
110 GtkWidget* | |
111 gtk_xemacs_new (struct frame *f) | |
112 { | |
113 GtkXEmacs *xemacs; | |
114 | |
2054 | 115 xemacs = (GtkXEmacs*) gtk_type_new (gtk_xemacs_get_type ()); |
462 | 116 xemacs->f = f; |
117 | |
118 return GTK_WIDGET (xemacs); | |
119 } | |
120 | |
121 static void | |
122 __nuke_background_items (GtkWidget *widget) | |
123 { | |
124 /* This bit of voodoo is here to get around the annoying flicker | |
125 when GDK tries to futz with our background pixmap as well as | |
126 XEmacs doing it | |
127 | |
128 We do NOT set the background of this widget window, that way | |
129 there is NO flickering, etc. The downside is the XEmacs frame | |
130 appears as 'seethru' when XEmacs is too busy to redraw the | |
131 frame. | |
132 | |
133 Well, wait, we do... otherwise there sre weird 'seethru' areas | |
134 even when XEmacs does a full redisplay. Most noticable in some | |
135 areas of the modeline, or in the right-hand-side of the window | |
136 between the scrollbar ad n the edge of the window. | |
137 */ | |
138 if (widget->window) | |
139 { | |
140 gdk_window_set_back_pixmap (widget->window, NULL, 0); | |
141 gdk_window_set_back_pixmap (widget->parent->window, NULL, 0); | |
142 gdk_window_set_background (widget->parent->window, | |
143 &widget->style->bg[GTK_STATE_NORMAL]); | |
144 gdk_window_set_background (widget->window, | |
145 &widget->style->bg[GTK_STATE_NORMAL]); | |
146 } | |
147 } | |
148 | |
149 extern Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w); | |
150 | |
151 /* From objects-gtk.c */ | |
152 extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp); | |
153 | |
154 #define convert_font(f) __get_gtk_font_truename (f, 0) | |
155 | |
778 | 156 #ifdef SMASH_FACE_FALLBACKS |
462 | 157 static void |
158 smash_face_fallbacks (struct frame *f, GtkStyle *style) | |
159 { | |
160 #define FROB(face,prop,slot) do { \ | |
161 Lisp_Object fallback = Qnil; \ | |
162 Lisp_Object specifier = Fget (face, prop, Qnil); \ | |
163 struct Lisp_Specifier *sp = NULL; \ | |
164 if (NILP (specifier)) continue; \ | |
165 sp = XSPECIFIER (specifier); \ | |
166 fallback = sp->fallback; \ | |
167 if (EQ (Fcar (Fcar (Fcar (fallback))), Qgtk)) \ | |
168 fallback = XCDR (fallback); \ | |
169 if (! NILP (slot)) \ | |
170 fallback = acons (list1 (Qgtk), \ | |
171 slot, \ | |
172 fallback); \ | |
173 set_specifier_fallback (specifier, fallback); \ | |
174 } while (0); | |
175 #define FROB_FACE(face,fg_slot,bg_slot) \ | |
176 do { \ | |
177 FROB (face, Qforeground, xemacs_gtk_convert_color (&style->fg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \ | |
178 FROB (face, Qbackground, xemacs_gtk_convert_color (&style->bg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \ | |
179 if (style->rc_style && style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]) \ | |
180 { \ | |
181 FROB (Vdefault_face, Qbackground_pixmap, \ | |
182 Fmake_image_instance (build_string (style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]), \ | |
183 f->device, Qnil, make_int (5))); \ | |
184 } \ | |
185 else \ | |
186 { \ | |
187 FROB (Vdefault_face, Qbackground_pixmap, Qnil); \ | |
188 } \ | |
189 } while (0) | |
190 | |
191 FROB (Vdefault_face, Qfont, convert_font (style->font)); | |
192 FROB_FACE (Vdefault_face, fg, bg); | |
193 FROB_FACE (Vgui_element_face, text, mid); | |
194 | |
195 #undef FROB | |
196 #undef FROB_FACE | |
197 } | |
778 | 198 #endif /* SMASH_FACE_FALLBACKS */ |
462 | 199 |
200 #ifdef HAVE_SCROLLBARS | |
201 static void | |
202 smash_scrollbar_specifiers (struct frame *f, GtkStyle *style) | |
203 { | |
204 Lisp_Object frame; | |
205 int slider_size = 0; | |
206 int hsize, vsize; | |
207 GtkRangeClass *klass; | |
208 | |
793 | 209 frame = wrap_frame (f); |
462 | 210 |
211 klass = (GtkRangeClass *) gtk_type_class (GTK_TYPE_SCROLLBAR); | |
212 slider_size = klass->slider_width; | |
213 hsize = slider_size + (style->klass->ythickness * 2); | |
214 vsize = slider_size + (style->klass->xthickness * 2); | |
215 | |
216 style = gtk_style_attach (style, | |
217 GTK_WIDGET (DEVICE_GTK_APP_SHELL (XDEVICE (FRAME_DEVICE (f))))->window); | |
218 | |
219 Fadd_spec_to_specifier (Vscrollbar_width, make_int (vsize), frame, Qnil, Qnil); | |
220 Fadd_spec_to_specifier (Vscrollbar_height, make_int (hsize), frame, Qnil, Qnil); | |
221 } | |
222 #endif /* HAVE_SCROLLBARS */ | |
223 | |
744 | 224 #ifdef HAVE_TOOLBARS |
225 extern Lisp_Object Vtoolbar_shadow_thickness; | |
226 | |
227 static void | |
228 smash_toolbar_specifiers(struct frame *f, GtkStyle *style) | |
229 { | |
230 Lisp_Object frame; | |
231 GtkStyleClass *klass = (GtkStyleClass *) style->klass; | |
232 | |
793 | 233 frame = wrap_frame (f); |
744 | 234 |
235 Fadd_spec_to_specifier (Vtoolbar_shadow_thickness, make_int (klass->xthickness), | |
236 Qnil, list2 (Qgtk, Qdefault), Qprepend); | |
237 } | |
238 #endif /* HAVE_TOOLBARS */ | |
239 | |
462 | 240 static void |
241 gtk_xemacs_realize (GtkWidget *widget) | |
242 { | |
243 parent_class->realize (widget); | |
244 gtk_xemacs_style_set (widget, gtk_widget_get_style (widget)); | |
245 } | |
246 | |
247 static void | |
248 gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style) | |
249 { | |
250 GtkStyle *new_style = gtk_widget_get_style (widget); | |
251 GtkXEmacs *x = GTK_XEMACS (widget); | |
252 | |
253 parent_class->style_set (widget, previous_style); | |
254 | |
255 if (x->f) | |
256 { | |
257 __nuke_background_items (widget); | |
778 | 258 #ifdef SMASH_FACE_FALLBACKS |
462 | 259 smash_face_fallbacks (x->f, new_style); |
260 #endif | |
744 | 261 #ifdef HAVE_SCROLLBARS |
462 | 262 smash_scrollbar_specifiers (x->f, new_style); |
744 | 263 #endif |
264 #ifdef HAVE_TOOLBARS | |
265 smash_toolbar_specifiers (x->f, new_style); | |
266 #endif | |
462 | 267 } |
268 } | |
269 | |
270 static void | |
271 gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition) | |
272 { | |
273 GtkXEmacs *x = GTK_XEMACS (widget); | |
274 struct frame *f = GTK_XEMACS_FRAME (x); | |
275 int width, height; | |
276 | |
277 if (f) | |
278 { | |
279 char_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f), | |
280 &width, &height); | |
281 requisition->width = width; | |
282 requisition->height = height; | |
283 } | |
284 else | |
285 { | |
286 parent_class->size_request (widget, requisition); | |
287 } | |
288 } | |
289 | |
2168 | 290 /* Assign a size and position to the child widgets. This differs from the |
291 super class method in that for all widgets except the scrollbars the size | |
292 and position are not caclulated here. This is because these widgets have | |
293 this function performed for them by the redisplay code (see | |
294 gtk_map_subwindow()). If the superclass method is called then the widgets | |
295 can change size and position as the two pieces of code move the widgets at | |
296 random. | |
297 */ | |
462 | 298 static void |
299 gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation) | |
300 { | |
301 GtkXEmacs *x = GTK_XEMACS (widget); | |
2168 | 302 GtkFixed *fixed = GTK_FIXED (widget); |
462 | 303 struct frame *f = GTK_XEMACS_FRAME (x); |
304 int columns, rows; | |
2168 | 305 GList *children; |
306 guint16 border_width; | |
462 | 307 |
2168 | 308 widget->allocation = *allocation; |
309 if (GTK_WIDGET_REALIZED (widget)) | |
310 gdk_window_move_resize (widget->window, | |
311 allocation->x, | |
312 allocation->y, | |
313 allocation->width, | |
314 allocation->height); | |
315 | |
316 border_width = GTK_CONTAINER (fixed)->border_width; | |
317 | |
318 children = fixed->children; | |
319 while (children) | |
320 { | |
2336 | 321 GtkFixedChild* child = (GtkFixedChild*) children->data; |
2168 | 322 children = children->next; |
323 | |
324 /* | |
325 Scrollbars are the only widget that is managed by GTK. See | |
326 comments in gtk_create_scrollbar_instance(). | |
327 */ | |
328 if (GTK_WIDGET_VISIBLE (child->widget) && | |
329 gtk_type_is_a(GTK_OBJECT_TYPE(child->widget), GTK_TYPE_SCROLLBAR)) | |
330 { | |
331 GtkAllocation child_allocation; | |
332 GtkRequisition child_requisition; | |
333 | |
334 gtk_widget_get_child_requisition (child->widget, &child_requisition); | |
335 child_allocation.x = child->x + border_width; | |
336 child_allocation.y = child->y + border_width; | |
337 child_allocation.width = child_requisition.width; | |
338 child_allocation.height = child_requisition.height; | |
339 gtk_widget_size_allocate (child->widget, &child_allocation); | |
340 } | |
341 } | |
462 | 342 |
343 if (f) | |
344 { | |
345 f->pixwidth = allocation->width; | |
346 f->pixheight = allocation->height; | |
347 | |
348 pixel_to_char_size (f, | |
349 allocation->width, | |
350 allocation->height, &columns, &rows); | |
351 | |
352 change_frame_size (f, rows, columns, 1); | |
353 } | |
354 } | |
355 | |
356 static void | |
357 gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area) | |
358 { | |
359 GtkXEmacs *x = GTK_XEMACS (widget); | |
360 struct frame *f = GTK_XEMACS_FRAME (x); | |
2195 | 361 |
362 if (GTK_WIDGET_DRAWABLE (widget)) | |
363 redisplay_redraw_exposed_area (f, area->x, area->y, area->width, | |
364 area->height); | |
462 | 365 } |
366 | |
367 static void | |
368 gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area) | |
369 { | |
370 GtkFixed *fixed = GTK_FIXED (widget); | |
371 GtkFixedChild *child; | |
372 GdkRectangle child_area; | |
373 GList *children; | |
374 | |
375 /* I need to manually iterate over the children instead of just | |
376 chaining to parent_class->draw() because it calls | |
377 gtk_fixed_paint() directly, which clears the background window, | |
378 which causes A LOT of flashing. */ | |
379 | |
2195 | 380 if (GTK_WIDGET_DRAWABLE (widget)) |
381 { | |
382 gtk_xemacs_paint (widget, area); | |
462 | 383 |
2195 | 384 children = fixed->children; |
462 | 385 |
2195 | 386 while (children) |
387 { | |
388 child = (GtkFixedChild*) children->data; | |
389 children = children->next; | |
390 /* #### This is what causes the scrollbar flickering! | |
391 Evidently the scrollbars pretty much take care of drawing | |
392 themselves in most cases. Then we come along and tell them | |
393 to redraw again! | |
462 | 394 |
2195 | 395 But if we just leave it out, then they do not get drawn |
396 correctly the first time! | |
462 | 397 |
2195 | 398 Scrollbar flickering has been greatly helped by the |
399 optimizations in scrollbar-gtk.c / | |
400 gtk_update_scrollbar_instance_status (), so this is not that | |
401 big a deal anymore. | |
402 */ | |
403 if (gtk_widget_intersect (child->widget, area, &child_area)) | |
404 { | |
405 gtk_widget_draw (child->widget, &child_area); | |
406 } | |
407 } | |
408 } | |
462 | 409 } |
410 | |
411 static gint | |
412 gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event) | |
413 { | |
414 GtkXEmacs *x = GTK_XEMACS (widget); | |
415 struct frame *f = GTK_XEMACS_FRAME (x); | |
416 GdkRectangle *a = &event->area; | |
417 | |
2195 | 418 if (GTK_WIDGET_DRAWABLE (widget)) |
419 { | |
420 /* This takes care of drawing the scrollbars, etc */ | |
421 parent_class->expose_event (widget, event); | |
462 | 422 |
2195 | 423 /* Now draw the actual frame data */ |
424 if (!check_for_ignored_expose (f, a->x, a->y, a->width, a->height) && | |
425 !find_matching_subwindow (f, a->x, a->y, a->width, a->height)) | |
426 redisplay_redraw_exposed_area (f, a->x, a->y, a->width, a->height); | |
427 return (TRUE); | |
428 } | |
3087 | 429 |
430 return FALSE; | |
462 | 431 } |
432 | |
433 Lisp_Object | |
2286 | 434 xemacs_gtk_convert_color(GdkColor *c, GtkWidget *UNUSED (w)) |
462 | 435 { |
436 char color_buf[255]; | |
437 | |
438 sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue); | |
439 | |
440 return (build_string (color_buf)); | |
441 } |