1 /* Device functions for X windows.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not in FSF. */
24 /* Original authors: Jamie Zawinski and the FSF */
25 /* Rewritten by Ben Wing and Chuck Thompson. */
26 /* Gtk flavor written by William Perry */
31 #include "console-gtk.h"
32 #include "gccache-gtk.h"
33 #include "glyphs-gtk.h"
34 #include "objects-gtk.h"
35 #include "gtk-xemacs.h"
41 #include "redisplay.h"
50 #include <libgnomeui/libgnomeui.h>
57 Lisp_Object Vdefault_gtk_device;
59 /* Qdisplay in general.c */
60 Lisp_Object Qinit_pre_gtk_win, Qinit_post_gtk_win;
62 /* The application class of Emacs. */
63 Lisp_Object Vgtk_emacs_application_class;
65 Lisp_Object Vgtk_initial_argv_list; /* #### ugh! */
66 Lisp_Object Vgtk_initial_geometry;
68 static void gtk_device_init_x_specific_cruft (struct device *d);
71 /************************************************************************/
72 /* helper functions */
73 /************************************************************************/
76 decode_gtk_device (Lisp_Object device)
78 XSETDEVICE (device, decode_device (device));
79 CHECK_GTK_DEVICE (device);
80 return XDEVICE (device);
84 /************************************************************************/
85 /* initializing a GTK connection */
86 /************************************************************************/
88 xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w);
90 extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp);
92 #define convert_font(f) __get_gtk_font_truename (f, 0)
95 allocate_gtk_device_struct (struct device *d)
97 d->device_data = xnew_and_zero (struct gtk_device);
98 DEVICE_GTK_DATA (d)->x_keysym_map_hashtable = Qnil;
102 gtk_init_device_class (struct device *d)
104 if (DEVICE_GTK_DEPTH(d) > 2)
106 switch (DEVICE_GTK_VISUAL(d)->type)
108 case GDK_VISUAL_STATIC_GRAY:
109 case GDK_VISUAL_GRAYSCALE:
110 DEVICE_CLASS (d) = Qgrayscale;
113 DEVICE_CLASS (d) = Qcolor;
117 DEVICE_CLASS (d) = Qmono;
120 #ifdef HAVE_GDK_IMLIB_INIT
121 extern void gdk_imlib_init(void);
124 extern void emacs_gtk_selection_handle (GtkWidget *,
125 GtkSelectionData *selection_data,
129 extern void emacs_gtk_selection_received (GtkWidget *widget,
130 GtkSelectionData *selection_data,
134 static CORBA_ORB orb;
137 DEFUN ("gtk-init", Fgtk_init, 1, 1, 0, /*
138 Initialize the GTK subsystem.
139 ARGS is a standard list of command-line arguments.
141 No effect if called more than once. Called automatically when
142 creating the first GTK device. Must be called manually from batch
156 make_argc_argv (args, &argc, &argv);
158 slow_down_interrupts ();
161 gnome_init ("InfoDock", EMACS_VERSION, argc, argv);
163 gnome_init ("XEmacs", EMACS_VERSION, argc, argv);
164 #endif /* INFODOCK */
166 gtk_init (&argc, &argv);
170 orb = oaf_init (argc, argv);
172 if (bonobo_init (orb, NULL, NULL) == FALSE)
174 g_warning ("Could not initialize bonobo...");
180 speed_up_interrupts ();
182 free_argc_argv (argv);
187 gtk_init_device (struct device *d, Lisp_Object props)
191 GtkWidget *app_shell = NULL;
192 GdkVisual *visual = NULL;
193 GdkColormap *cmap = NULL;
195 XSETDEVICE (device, d);
197 /* gtk_init() and even gtk_check_init() are so brain dead that
198 getting an empty argv array causes them to abort. */
199 if (NILP (Vgtk_initial_argv_list))
201 signal_simple_error ("gtk-initial-argv-list must be set before creating Gtk devices", Vgtk_initial_argv_list);
205 allocate_gtk_device_struct (d);
206 display = DEVICE_CONNECTION (d);
208 /* Attempt to load a site-specific gtkrc */
210 Lisp_Object gtkrc = Fexpand_file_name (build_string ("gtkrc"), Vdata_directory);
211 gchar **default_files = gtk_rc_get_default_files ();
216 /* Found one, load it up! */
217 gchar **new_rc_files = NULL;
220 for (num_files = 0; default_files[num_files]; num_files++);
222 new_rc_files = xnew_array_and_zero (gchar *, num_files + 3);
224 new_rc_files[0] = XSTRING_DATA (gtkrc);
225 for (ctr = 1; default_files[ctr-1]; ctr++)
226 new_rc_files[ctr] = g_strdup (default_files[ctr-1]);
228 gtk_rc_set_default_files (new_rc_files);
230 for (ctr = 1; new_rc_files[ctr]; ctr++)
231 free(new_rc_files[ctr]);
233 xfree (new_rc_files);
237 Fgtk_init (Vgtk_initial_argv_list);
240 gdk_set_use_xshm (FALSE);
243 /* We attempt to load this file so that the user can set
244 ** gtk-initial-geometry and not need GNOME & session management to
245 ** set their default frame size. It also avoids the flicker
246 ** associated with setting the frame size in your .emacs file.
248 call4 (Qload, build_string ("~/.xemacs/gtk-options.el"), Qt, Qt, Qt);
250 #ifdef HAVE_GDK_IMLIB_INIT
251 /* Some themes in Gtk are so lame (most notably the Pixmap theme)
252 that they rely on gdk_imlib, but don't call its initialization
253 routines. This makes them USELESS for non-gnome applications.
254 So we bend over backwards to try and make them work. Losers. */
258 if (NILP (DEVICE_NAME (d)))
259 DEVICE_NAME (d) = display;
261 /* Always search for the best visual */
262 visual = gdk_visual_get_best();
263 cmap = gdk_colormap_new (visual, TRUE);
265 DEVICE_GTK_VISUAL (d) = visual;
266 DEVICE_GTK_COLORMAP (d) = cmap;
267 DEVICE_GTK_DEPTH (d) = visual->depth;
270 GtkWidget *w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
272 app_shell = gtk_xemacs_new (NULL);
273 gtk_container_add (GTK_CONTAINER (w), app_shell);
275 gtk_widget_realize (w);
278 DEVICE_GTK_APP_SHELL (d) = app_shell;
280 /* Realize the app_shell so that its window exists for GC creation
282 gtk_widget_realize (GTK_WIDGET (app_shell));
284 /* Need to set up some selection handlers */
285 gtk_selection_add_target (GTK_WIDGET (app_shell), GDK_SELECTION_PRIMARY,
286 GDK_SELECTION_TYPE_STRING, 0);
288 gtk_signal_connect (GTK_OBJECT (app_shell), "selection_get",
289 GTK_SIGNAL_FUNC (emacs_gtk_selection_handle), NULL);
290 gtk_signal_connect (GTK_OBJECT (app_shell), "selection_received",
291 GTK_SIGNAL_FUNC (emacs_gtk_selection_received), NULL);
293 DEVICE_GTK_WM_COMMAND_FRAME (d) = Qnil;
295 gtk_init_modifier_mapping (d);
297 gtk_device_init_x_specific_cruft (d);
302 DEVICE_GTK_GC_CACHE (d) = make_gc_cache (GTK_WIDGET (app_shell));
303 DEVICE_GTK_GRAY_PIXMAP (d) = NULL;
305 gtk_init_device_class (d);
307 /* Run the elisp side of the X device initialization. */
308 call0 (Qinit_pre_gtk_win);
312 gtk_finish_init_device (struct device *d, Lisp_Object props)
314 call0 (Qinit_post_gtk_win);
318 gtk_mark_device (struct device *d)
320 mark_object (DEVICE_GTK_WM_COMMAND_FRAME (d));
321 mark_object (DEVICE_GTK_DATA (d)->x_keysym_map_hashtable);
325 /************************************************************************/
326 /* closing an X connection */
327 /************************************************************************/
330 free_gtk_device_struct (struct device *d)
332 xfree (d->device_data);
336 gtk_delete_device (struct device *d)
341 extern void (*__free_hook)();
345 XSETDEVICE (device, d);
349 checking_free = (__free_hook != 0);
351 /* Disable strict free checking, to avoid bug in X library */
353 disable_strict_free_check ();
356 free_gc_cache (DEVICE_GTK_GC_CACHE (d));
360 enable_strict_free_check ();
364 if (EQ (device, Vdefault_gtk_device))
366 Lisp_Object devcons, concons;
367 /* #### handle deleting last X device */
368 Vdefault_gtk_device = Qnil;
369 DEVICE_LOOP_NO_BREAK (devcons, concons)
371 if (DEVICE_GTK_P (XDEVICE (XCAR (devcons))) &&
372 !EQ (device, XCAR (devcons)))
374 Vdefault_gtk_device = XCAR (devcons);
380 free_gtk_device_struct (d);
384 /************************************************************************/
385 /* handle X errors */
386 /************************************************************************/
389 gtk_event_name (GdkEventType event_type)
391 GtkEnumValue *vals = gtk_type_enum_get_values (GTK_TYPE_GDK_EVENT_TYPE);
393 while (vals && (vals->value != event_type)) vals++;
396 return (vals->value_nick);
402 /************************************************************************/
403 /* display information functions */
404 /************************************************************************/
406 DEFUN ("default-gtk-device", Fdefault_gtk_device, 0, 0, 0, /*
407 Return the default GTK device for resourcing.
408 This is the first-created GTK device that still exists.
412 return Vdefault_gtk_device;
415 DEFUN ("gtk-display-visual-class", Fgtk_display_visual_class, 0, 1, 0, /*
416 Return the visual class of the GTK display DEVICE is using.
417 The returned value will be one of the symbols `static-gray', `gray-scale',
418 `static-color', `pseudo-color', `true-color', or `direct-color'.
422 GdkVisual *vis = DEVICE_GTK_VISUAL (decode_gtk_device (device));
425 case GDK_VISUAL_STATIC_GRAY: return intern ("static-gray");
426 case GDK_VISUAL_GRAYSCALE: return intern ("gray-scale");
427 case GDK_VISUAL_STATIC_COLOR: return intern ("static-color");
428 case GDK_VISUAL_PSEUDO_COLOR: return intern ("pseudo-color");
429 case GDK_VISUAL_TRUE_COLOR: return intern ("true-color");
430 case GDK_VISUAL_DIRECT_COLOR: return intern ("direct-color");
432 error ("display has an unknown visual class");
433 return Qnil; /* suppress compiler warning */
437 DEFUN ("gtk-display-visual-depth", Fgtk_display_visual_depth, 0, 1, 0, /*
438 Return the bitplane depth of the visual the GTK display DEVICE is using.
442 return make_int (DEVICE_GTK_DEPTH (decode_gtk_device (device)));
446 gtk_device_system_metrics (struct device *d,
447 enum device_metrics m)
450 GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (DEVICE_GTK_APP_SHELL (d)));
452 style = gtk_style_attach (style, w);
458 return Fcons (make_int (gdk_screen_width ()),
459 make_int (gdk_screen_height ()));
460 case DM_size_device_mm:
461 return Fcons (make_int (gdk_screen_width_mm ()),
462 make_int (gdk_screen_height_mm ()));
463 case DM_num_color_cells:
464 return make_int (gdk_colormap_get_system_size ());
465 case DM_num_bit_planes:
466 return make_int (DEVICE_GTK_DEPTH (d));
469 case DM_color_default:
470 case DM_color_select:
471 case DM_color_balloon:
472 case DM_color_3d_face:
473 case DM_color_3d_light:
474 case DM_color_3d_dark:
476 case DM_color_menu_highlight:
477 case DM_color_menu_button:
478 case DM_color_menu_disabled:
479 case DM_color_toolbar:
480 case DM_color_scrollbar:
481 case DM_color_desktop:
482 case DM_color_workspace:
483 case DM_font_default:
484 case DM_font_menubar:
487 case DM_size_scrollbar:
489 case DM_size_toolbar:
490 case DM_size_toolbar_button:
491 case DM_size_toolbar_border:
493 case DM_size_icon_small:
494 case DM_size_workspace:
496 case DM_mouse_buttons:
497 case DM_swap_buttons:
502 default: /* No such device metric property for GTK devices */
507 DEFUN ("gtk-keysym-on-keyboard-p", Fgtk_keysym_on_keyboard_p, 1, 2, 0, /*
508 Return true if KEYSYM names a key on the keyboard of DEVICE.
509 More precisely, return true if some keystroke (possibly including modifiers)
510 on the keyboard of DEVICE keys generates KEYSYM.
511 Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
512 /usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
513 The keysym name can be provided in two forms:
514 - if keysym is a string, it must be the name as known to X windows.
515 - if keysym is a symbol, it must be the name as known to XEmacs.
516 The two names differ in capitalization and underscoring.
520 struct device *d = decode_device (device);
522 if (!DEVICE_GTK_P (d))
523 signal_simple_error ("Not a GTK device", device);
525 return (NILP (Fgethash (keysym, DEVICE_GTK_DATA (d)->x_keysym_map_hashtable, Qnil)) ?
530 /************************************************************************/
531 /* grabs and ungrabs */
532 /************************************************************************/
534 DEFUN ("gtk-grab-pointer", Fgtk_grab_pointer, 0, 3, 0, /*
535 Grab the pointer and restrict it to its current window.
536 If optional DEVICE argument is nil, the default device will be used.
537 If optional CURSOR argument is non-nil, change the pointer shape to that
538 until `gtk-ungrab-pointer' is called (it should be an object returned by the
539 `make-cursor-glyph' function).
540 If the second optional argument IGNORE-KEYBOARD is non-nil, ignore all
541 keyboard events during the grab.
542 Returns t if the grab is successful, nil otherwise.
544 (device, cursor, ignore_keyboard))
548 struct device *d = decode_gtk_device (device);
552 CHECK_POINTER_GLYPH (cursor);
553 cursor = glyph_image_instance (cursor, device, ERROR_ME, 0);
556 /* We should call gdk_pointer_grab() and (possibly) gdk_keyboard_grab() here instead */
557 w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (device_selected_frame (d)));
559 result = gdk_pointer_grab (w, FALSE,
560 GDK_POINTER_MOTION_MASK |
561 GDK_POINTER_MOTION_HINT_MASK |
562 GDK_BUTTON1_MOTION_MASK |
563 GDK_BUTTON2_MOTION_MASK |
564 GDK_BUTTON3_MOTION_MASK |
565 GDK_BUTTON_PRESS_MASK |
566 GDK_BUTTON_RELEASE_MASK,
568 NULL, /* #### BILL!!! Need to create a GdkCursor * as necessary! */
571 return (result == 0) ? Qt : Qnil;
574 DEFUN ("gtk-ungrab-pointer", Fgtk_ungrab_pointer, 0, 1, 0, /*
575 Release a pointer grab made with `gtk-grab-pointer'.
576 If optional first arg DEVICE is nil the default device is used.
577 If it is t the pointer will be released on all GTK devices.
581 if (!EQ (device, Qt))
583 gdk_pointer_ungrab (GDK_CURRENT_TIME);
587 Lisp_Object devcons, concons;
589 DEVICE_LOOP_NO_BREAK (devcons, concons)
591 struct device *d = XDEVICE (XCAR (devcons));
593 if (DEVICE_GTK_P (d))
594 gdk_pointer_ungrab (GDK_CURRENT_TIME);
600 DEFUN ("gtk-grab-keyboard", Fgtk_grab_keyboard, 0, 1, 0, /*
601 Grab the keyboard on the given device (defaulting to the selected one).
602 So long as the keyboard is grabbed, all keyboard events will be delivered
603 to emacs -- it is not possible for other clients to eavesdrop on them.
604 Ungrab the keyboard with `gtk-ungrab-keyboard' (use an unwind-protect).
605 Returns t if the grab is successful, nil otherwise.
609 struct device *d = decode_gtk_device (device);
610 GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (device_selected_frame (d)));
612 gdk_keyboard_grab (w, FALSE, GDK_CURRENT_TIME );
617 DEFUN ("gtk-ungrab-keyboard", Fgtk_ungrab_keyboard, 0, 1, 0, /*
618 Release a keyboard grab made with `gtk-grab-keyboard'.
622 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
627 /************************************************************************/
629 /************************************************************************/
630 DEFUN ("gtk-style-info", Fgtk_style_info, 0, 1, 0, /*
631 Get the style information for a Gtk device.
635 struct device *d = decode_device (device);
636 GtkStyle *style = NULL;
637 Lisp_Object result = Qnil;
638 GtkWidget *app_shell = GTK_WIDGET (DEVICE_GTK_APP_SHELL (d));
639 GdkWindow *w = GET_GTK_WIDGET_WINDOW (app_shell);
641 if (!DEVICE_GTK_P (d))
644 style = gtk_widget_get_style (app_shell);
645 style = gtk_style_attach (style, w);
647 if (!style) return (Qnil);
649 #define FROB_COLOR(slot, name) \
650 result = nconc2 (result, \
651 list2 (intern (name), \
652 list5 (xemacs_gtk_convert_color (&style->slot[GTK_STATE_NORMAL], app_shell),\
653 xemacs_gtk_convert_color (&style->slot[GTK_STATE_ACTIVE], app_shell),\
654 xemacs_gtk_convert_color (&style->slot[GTK_STATE_PRELIGHT], app_shell),\
655 xemacs_gtk_convert_color (&style->slot[GTK_STATE_SELECTED], app_shell),\
656 xemacs_gtk_convert_color (&style->slot[GTK_STATE_INSENSITIVE], app_shell))))
658 FROB_COLOR (fg, "foreground");
659 FROB_COLOR (bg, "background");
660 FROB_COLOR (light, "light");
661 FROB_COLOR (dark, "dark");
662 FROB_COLOR (mid, "mid");
663 FROB_COLOR (text, "text");
664 FROB_COLOR (base, "base");
667 result = nconc2 (result, list2 (Qfont, convert_font (style->font)));
669 #define FROB_PIXMAP(state) (style->rc_style->bg_pixmap_name[state] ? build_string (style->rc_style->bg_pixmap_name[state]) : Qnil)
672 result = nconc2 (result, list2 (Qbackground,
673 list5 ( FROB_PIXMAP (GTK_STATE_NORMAL),
674 FROB_PIXMAP (GTK_STATE_ACTIVE),
675 FROB_PIXMAP (GTK_STATE_PRELIGHT),
676 FROB_PIXMAP (GTK_STATE_SELECTED),
677 FROB_PIXMAP (GTK_STATE_INSENSITIVE))));
684 gtk_device_implementation_flags (void)
686 return 0; /* XDEVIMPF_PIXEL_GEOMETRY; */
690 /************************************************************************/
692 /************************************************************************/
695 syms_of_device_gtk (void)
697 DEFSUBR (Fdefault_gtk_device);
698 DEFSUBR (Fgtk_keysym_on_keyboard_p);
699 DEFSUBR (Fgtk_display_visual_class);
700 DEFSUBR (Fgtk_display_visual_depth);
701 DEFSUBR (Fgtk_style_info);
702 DEFSUBR (Fgtk_grab_pointer);
703 DEFSUBR (Fgtk_ungrab_pointer);
704 DEFSUBR (Fgtk_grab_keyboard);
705 DEFSUBR (Fgtk_ungrab_keyboard);
708 defsymbol (&Qinit_pre_gtk_win, "init-pre-gtk-win");
709 defsymbol (&Qinit_post_gtk_win, "init-post-gtk-win");
713 console_type_create_device_gtk (void)
715 CONSOLE_HAS_METHOD (gtk, init_device);
716 CONSOLE_HAS_METHOD (gtk, finish_init_device);
717 CONSOLE_HAS_METHOD (gtk, mark_device);
718 CONSOLE_HAS_METHOD (gtk, delete_device);
719 CONSOLE_HAS_METHOD (gtk, device_system_metrics);
720 CONSOLE_HAS_METHOD (gtk, device_implementation_flags);
724 vars_of_device_gtk (void)
728 staticpro (&Vdefault_gtk_device);
730 DEFVAR_LISP ("gtk-initial-argv-list", &Vgtk_initial_argv_list /*
731 You don't want to know.
732 This is used during startup to communicate the remaining arguments in
733 `command-line-args-left' to the C code, which passes the args to
734 the GTK initialization code, which removes some args, and then the
735 args are placed back into `gtk-initial-arg-list' and thence into
736 `command-line-args-left'. Perhaps `command-line-args-left' should
740 DEFVAR_LISP ("gtk-initial-geometry", &Vgtk_initial_geometry /*
741 You don't want to know.
742 This is used during startup to communicate the default geometry to GTK.
745 Vdefault_gtk_device = Qnil;
746 Vgtk_initial_geometry = Qnil;
747 Vgtk_initial_argv_list = Qnil;
750 #include <gdk/gdkx.h>
752 gtk_device_init_x_specific_cruft (struct device *d)
754 DEVICE_INFD (d) = DEVICE_OUTFD (d) = ConnectionNumber (GDK_DISPLAY ());