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