1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include "config.h"
22:
23: #ifdef USE_GTK
24: #include <string.h>
25: #include <signal.h>
26: #include <stdio.h>
27: #include "lisp.h"
28: #include "xterm.h"
29: #include "blockinput.h"
30: #include "syssignal.h"
31: #include "window.h"
32: #include "atimer.h"
33: #include "gtkutil.h"
34: #include "termhooks.h"
35: #include "keyboard.h"
36: #include "charset.h"
37: #include "coding.h"
38: #include <gdk/gdkkeysyms.h>
39:
40:
41: #define FRAME_TOTAL_PIXEL_HEIGHT(f) \
42: (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
43:
44:
45: #define SSDATA(x) ((char *) SDATA (x))
46:
47: ^L
48:
49:
50:
51:
52: #ifdef HAVE_GTK_MULTIDISPLAY
53:
54:
55:
56: static GdkDisplay *
57: xg_get_gdk_display (dpy)
58: Display *dpy;
59: {
60: return gdk_x11_lookup_xdisplay (dpy);
61: }
62:
63:
64:
65:
66:
67: static void
68: xg_set_screen (w, f)
69: GtkWidget *w;
70: FRAME_PTR f;
71: {
72: if (FRAME_X_DISPLAY (f) != GDK_DISPLAY ())
73: {
74: GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
75: GdkScreen *gscreen = gdk_display_get_default_screen (gdpy);
76:
77: if (GTK_IS_MENU (w))
78: gtk_menu_set_screen (GTK_MENU (w), gscreen);
79: else
80: gtk_window_set_screen (GTK_WINDOW (w), gscreen);
81: }
82: }
83:
84:
85: #else
86:
87:
88:
89:
90: #define xg_set_screen(w, f)
91: #define gdk_xid_table_lookup_for_display(dpy, w) gdk_xid_table_lookup (w)
92: #define gdk_pixmap_foreign_new_for_display(dpy, p) gdk_pixmap_foreign_new (p)
93: #define gdk_cursor_new_for_display(dpy, c) gdk_cursor_new (c)
94: #define gdk_x11_lookup_xdisplay(dpy) 0
95: #define GdkDisplay void
96:
97: #endif
98:
99:
100:
101:
102:
103:
104:
105:
106: int
107: xg_display_open (display_name, dpy)
108: char *display_name;
109: Display **dpy;
110: {
111: #ifdef HAVE_GTK_MULTIDISPLAY
112: GdkDisplay *gdpy;
113:
114: gdpy = gdk_display_open (display_name);
115: *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL;
116:
117: return gdpy != NULL;
118:
119: #else
120:
121: return -1;
122: #endif
123: }
124:
125:
126:
127:
128: void
129: xg_display_close (Display *dpy)
130: {
131: #ifdef HAVE_GTK_MULTIDISPLAY
132: GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy);
133:
134:
135:
136: if (gdk_display_get_default () == gdpy)
137: {
138: struct x_display_info *dpyinfo;
139: Display *new_dpy = 0;
140: GdkDisplay *gdpy_new;
141:
142:
143: for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
144: if (dpyinfo->display != dpy)
145: {
146: new_dpy = dpyinfo->display;
147: break;
148: }
149:
150: if (! new_dpy) return;
151:
152: gdpy_new = gdk_x11_lookup_xdisplay (new_dpy);
153: gdk_display_manager_set_default_display (gdk_display_manager_get (),
154: gdpy_new);
155: }
156:
157:
158:
159:
160:
161: #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 10
162: g_object_run_dispose (G_OBJECT (gdpy));
163: #else
164:
165: gdk_display_close (gdpy);
166: #endif
167: #endif
168: }
169:
170: ^L
171:
172:
173:
174:
175:
176: static struct atimer *xg_timer;
177:
178:
179:
180: static widget_value *widget_value_free_list;
181: static int malloc_cpt;
182:
183:
184:
185:
186:
187:
188: widget_value *
189: malloc_widget_value ()
190: {
191: widget_value *wv;
192: if (widget_value_free_list)
193: {
194: wv = widget_value_free_list;
195: widget_value_free_list = wv->free_list;
196: wv->free_list = 0;
197: }
198: else
199: {
200: wv = (widget_value *) xmalloc (sizeof (widget_value));
201: malloc_cpt++;
202: }
203: memset (wv, 0, sizeof (widget_value));
204: return wv;
205: }
206:
207:
208:
209:
210: void
211: free_widget_value (wv)
212: widget_value *wv;
213: {
214: if (wv->free_list)
215: abort ();
216:
217: if (malloc_cpt > 25)
218: {
219:
220:
221: free (wv);
222: malloc_cpt--;
223: }
224: else
225: {
226: wv->free_list = widget_value_free_list;
227: widget_value_free_list = wv;
228: }
229: }
230:
231:
232:
233:
234:
235: GdkCursor *
236: xg_create_default_cursor (dpy)
237: Display *dpy;
238: {
239: GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy);
240: return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR);
241: }
242:
243:
244:
245: static GdkPixbuf *
246: xg_get_pixbuf_from_pix_and_mask (gpix, gmask, cmap)
247: GdkPixmap *gpix;
248: GdkPixmap *gmask;
249: GdkColormap *cmap;
250: {
251: int x, y, width, height, rowstride, mask_rowstride;
252: GdkPixbuf *icon_buf, *tmp_buf;
253: guchar *pixels;
254: guchar *mask_pixels;
255:
256: gdk_drawable_get_size (gpix, &width, &height);
257: tmp_buf = gdk_pixbuf_get_from_drawable (NULL, gpix, cmap,
258: 0, 0, 0, 0, width, height);
259: icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0);
260: g_object_unref (G_OBJECT (tmp_buf));
261:
262: if (gmask)
263: {
264: GdkPixbuf *mask_buf = gdk_pixbuf_get_from_drawable (NULL,
265: gmask,
266: NULL,
267: 0, 0, 0, 0,
268: width, height);
269: guchar *pixels = gdk_pixbuf_get_pixels (icon_buf);
270: guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf);
271: int rowstride = gdk_pixbuf_get_rowstride (icon_buf);
272: int mask_rowstride = gdk_pixbuf_get_rowstride (mask_buf);
273: int y;
274:
275: for (y = 0; y < height; ++y)
276: {
277: guchar *iconptr, *maskptr;
278: int x;
279:
280: iconptr = pixels + y * rowstride;
281: maskptr = mask_pixels + y * mask_rowstride;
282:
283: for (x = 0; x < width; ++x)
284: {
285:
286:
287: if (maskptr[0] == 0)
288: iconptr[3] = 0;
289:
290: iconptr += rowstride/width;
291: maskptr += mask_rowstride/width;
292: }
293: }
294:
295: g_object_unref (G_OBJECT (mask_buf));
296: }
297:
298: return icon_buf;
299: }
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312: static GtkWidget *
313: xg_get_image_for_pixmap (f, img, widget, old_widget)
314: FRAME_PTR f;
315: struct image *img;
316: GtkWidget *widget;
317: GtkImage *old_widget;
318: {
319: GdkPixmap *gpix;
320: GdkPixmap *gmask;
321: GdkDisplay *gdpy;
322:
323:
324:
325:
326: Lisp_Object specified_file = Qnil;
327: Lisp_Object tail;
328: Lisp_Object file;
329: extern Lisp_Object QCfile;
330:
331: for (tail = XCDR (img->spec);
332: NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail));
333: tail = XCDR (XCDR (tail)))
334: if (EQ (XCAR (tail), QCfile))
335: specified_file = XCAR (XCDR (tail));
336:
337:
338:
339:
340:
341: if (STRINGP (specified_file)
342: && STRINGP (file = x_find_image_file (specified_file)))
343: {
344: if (! old_widget)
345: old_widget = GTK_IMAGE (gtk_image_new_from_file (SSDATA (file)));
346: else
347: gtk_image_set_from_file (old_widget, SSDATA (file));
348:
349: return GTK_WIDGET (old_widget);
350: }
351:
352:
353:
354:
355:
356: gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
357: gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap);
358: gmask = img->mask ? gdk_pixmap_foreign_new_for_display (gdpy, img->mask) : 0;
359:
360: if (x_screen_planes (f) > 8 || x_screen_planes (f) == 1)
361: {
362: if (! old_widget)
363: old_widget = GTK_IMAGE (gtk_image_new_from_pixmap (gpix, gmask));
364: else
365: gtk_image_set_from_pixmap (old_widget, gpix, gmask);
366: }
367: else
368: {
369:
370:
371:
372:
373:
374:
375:
376: GdkColormap *cmap = gtk_widget_get_colormap (widget);
377: GdkPixbuf *icon_buf = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, cmap);
378:
379: if (! old_widget)
380: old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
381: else
382: gtk_image_set_from_pixbuf (old_widget, icon_buf);
383:
384: g_object_unref (G_OBJECT (icon_buf));
385: }
386:
387: g_object_unref (G_OBJECT (gpix));
388: if (gmask) g_object_unref (G_OBJECT (gmask));
389:
390: return GTK_WIDGET (old_widget);
391: }
392:
393:
394:
395:
396:
397:
398: static void
399: xg_set_cursor (w, cursor)
400: GtkWidget *w;
401: GdkCursor *cursor;
402: {
403: GList *children = gdk_window_peek_children (w->window);
404:
405: gdk_window_set_cursor (w->window, cursor);
406:
407:
408:
409:
410:
411:
412: for ( ; children; children = g_list_next (children))
413: gdk_window_set_cursor (GDK_WINDOW (children->data), cursor);
414: }
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426: static void
427: xg_process_timeouts (timer)
428: struct atimer *timer;
429: {
430: BLOCK_INPUT;
431:
432:
433: while (gtk_events_pending ())
434: gtk_main_iteration ();
435: UNBLOCK_INPUT;
436: }
437:
438:
439:
440:
441:
442: static void
443: xg_start_timer ()
444: {
445: if (! xg_timer)
446: {
447: EMACS_TIME interval;
448: EMACS_SET_SECS_USECS (interval, 0, 100000);
449: xg_timer = start_atimer (ATIMER_CONTINUOUS,
450: interval,
451: xg_process_timeouts,
452: 0);
453: }
454: }
455:
456:
457:
458: static void
459: xg_stop_timer ()
460: {
461: if (xg_timer)
462: {
463: cancel_atimer (xg_timer);
464: xg_timer = 0;
465: }
466: }
467:
468:
469:
470: static void
471: xg_list_insert (xg_list_node *list, xg_list_node *node)
472: {
473: xg_list_node *list_start = list->next;
474:
475: if (list_start) list_start->prev = node;
476: node->next = list_start;
477: node->prev = 0;
478: list->next = node;
479: }
480:
481:
482:
483: static void
484: xg_list_remove (xg_list_node *list, xg_list_node *node)
485: {
486: xg_list_node *list_start = list->next;
487: if (node == list_start)
488: {
489: list->next = node->next;
490: if (list->next) list->next->prev = 0;
491: }
492: else
493: {
494: node->prev->next = node->next;
495: if (node->next) node->next->prev = node->prev;
496: }
497: }
498:
499:
500:
501:
502:
503:
504: static char *
505: get_utf8_string (str)
506: char *str;
507: {
508: char *utf8_str = str;
509:
510: if (!str) return NULL;
511:
512:
513: if (!g_utf8_validate (str, -1, NULL))
514: utf8_str = g_locale_to_utf8 (str, -1, 0, 0, 0);
515:
516: if (!utf8_str)
517: {
518:
519: size_t nr_bad = 0;
520: gsize bytes_read;
521: gsize bytes_written;
522: unsigned char *p = (unsigned char *)str;
523: char *cp, *up;
524: GError *error = NULL;
525:
526: while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
527: &bytes_written, &error))
528: && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
529: {
530: ++nr_bad;
531: p += bytes_written+1;
532: g_error_free (error);
533: error = NULL;
534: }
535:
536: if (error)
537: {
538: g_error_free (error);
539: error = NULL;
540: }
541: if (cp) g_free (cp);
542:
543: up = utf8_str = xmalloc (strlen (str) + nr_bad * 4 + 1);
544: p = (unsigned char *)str;
545:
546: while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
547: &bytes_written, &error))
548: && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
549: {
550: strncpy (up, (char *)p, bytes_written);
551: sprintf (up + bytes_written, "\\%03o", p[bytes_written]);
552: up[bytes_written+4] = '\0';
553: up += bytes_written+4;
554: p += bytes_written+1;
555: g_error_free (error);
556: error = NULL;
557: }
558:
559: if (cp)
560: {
561: strcat (utf8_str, cp);
562: g_free (cp);
563: }
564: if (error)
565: {
566: g_error_free (error);
567: error = NULL;
568: }
569: }
570: return utf8_str;
571: }
572:
573:
574: ^L
575:
576:
577:
578:
579:
580:
581:
582:
583:
584: static void
585: xg_set_geometry (f)
586: FRAME_PTR f;
587: {
588: if (f->size_hint_flags & USPosition)
589: {
590: int left = f->left_pos;
591: int xneg = f->size_hint_flags & XNegative;
592: int top = f->top_pos;
593: int yneg = f->size_hint_flags & YNegative;
594: char geom_str[32];
595:
596: if (xneg)
597: left = -left;
598: if (yneg)
599: top = -top;
600:
601: sprintf (geom_str, "=%dx%d%c%d%c%d",
602: FRAME_PIXEL_WIDTH (f),
603: FRAME_TOTAL_PIXEL_HEIGHT (f),
604: (xneg ? '-' : '+'), left,
605: (yneg ? '-' : '+'), top);
606:
607: if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
608: geom_str))
609: fprintf (stderr, "Failed to parse: '%s'\n", geom_str);
610: } else if (f->size_hint_flags & PPosition) {
611: gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
612: f->left_pos, f->top_pos);
613: }
614: }
615:
616:
617: