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 SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: Not in FSF. */
23 /* Original authors: Jamie Zawinski and the FSF */
24 /* Rewritten by Ben Wing and Chuck Thompson. */
25 /* Gtk flavor written by William Perry */
30 #include "console-gtk.h"
31 #include "gccache-gtk.h"
32 #include "glyphs-gtk.h"
33 #include "objects-gtk.h"
34 #include "gtk-xemacs.h"
37 #include "events/events.h"
40 #include "ui/redisplay.h"
42 #include "ui/window.h"
49 #include <libgnomeui/libgnomeui.h>
56 Lisp_Object Vdefault_gtk_device;
58 /* Qdisplay in general.c */
59 Lisp_Object Qinit_pre_gtk_win, Qinit_post_gtk_win;
61 /* The application class of Emacs. */
62 Lisp_Object Vgtk_emacs_application_class;
64 Lisp_Object Vgtk_initial_argv_list; /* #### ugh! */
65 Lisp_Object Vgtk_initial_geometry;
67 static void gtk_device_init_x_specific_cruft(struct device *d);
69 /************************************************************************/
70 /* helper functions */
71 /************************************************************************/
73 struct device *decode_gtk_device(Lisp_Object device)
75 XSETDEVICE(device, decode_device(device));
76 CHECK_GTK_DEVICE(device);
77 return XDEVICE(device);
80 /************************************************************************/
81 /* initializing a GTK connection */
82 /************************************************************************/
83 extern Lisp_Object xemacs_gtk_convert_color(GdkColor * c, GtkWidget * w);
85 extern Lisp_Object __get_gtk_font_truename(GdkFont * gdk_font, int expandp);
87 #define convert_font(f) __get_gtk_font_truename (f, 0)
89 static void allocate_gtk_device_struct(struct device *d)
91 d->device_data = xnew_and_zero(struct gtk_device);
92 DEVICE_GTK_DATA(d)->x_keysym_map_hashtable = Qnil;
95 static void gtk_init_device_class(struct device *d)
97 if (DEVICE_GTK_DEPTH(d) > 2) {
98 switch (DEVICE_GTK_VISUAL(d)->type) {
99 case GDK_VISUAL_STATIC_GRAY:
100 case GDK_VISUAL_GRAYSCALE:
101 DEVICE_CLASS(d) = Qgrayscale;
104 DEVICE_CLASS(d) = Qcolor;
107 DEVICE_CLASS(d) = Qmono;
110 #ifdef HAVE_GDK_IMLIB_INIT
111 extern void gdk_imlib_init(void);
114 extern void emacs_gtk_selection_handle(GtkWidget *,
115 GtkSelectionData * selection_data,
117 guint time_stamp, gpointer data);
118 extern void emacs_gtk_selection_clear_event_handle(GtkWidget * widget,
119 GdkEventSelection * event,
121 extern void emacs_gtk_selection_received(GtkWidget * widget,
122 GtkSelectionData * selection_data,
126 static CORBA_ORB orb;
129 DEFUN("gtk-init", Fgtk_init, 1, 1, 0, /*
130 Initialize the GTK subsystem.
131 ARGS is a standard list of command-line arguments.
133 No effect if called more than once. Called automatically when
134 creating the first GTK device. Must be called manually from batch
147 make_argc_argv(args, &argc, &argv);
149 slow_down_interrupts();
152 gnome_init("InfoDock", EMACS_VERSION, argc, argv);
154 gnome_init("SXEmacs", EMACS_VERSION, argc, argv);
155 #endif /* INFODOCK */
157 gtk_init(&argc, &argv);
161 orb = oaf_init(argc, argv);
163 if (bonobo_init(orb, NULL, NULL) == FALSE) {
164 g_warning("Could not initialize bonobo...");
170 speed_up_interrupts();
172 free_argc_argv(argv);
176 static void gtk_init_device(struct device *d, Lisp_Object props)
180 GtkWidget *app_shell = NULL;
181 GdkVisual *visual = NULL;
182 GdkColormap *cmap = NULL;
184 XSETDEVICE(device, d);
186 /* gtk_init() and even gtk_check_init() are so brain dead that
187 getting an empty argv array causes them to abort. */
188 if (NILP(Vgtk_initial_argv_list)) {
190 ("gtk-initial-argv-list must be set before creating Gtk devices",
191 Vgtk_initial_argv_list);
195 allocate_gtk_device_struct(d);
196 display = DEVICE_CONNECTION(d);
198 /* Attempt to load a site-specific gtkrc */
201 Fexpand_file_name(build_string("gtkrc"), Vdata_directory);
202 gchar **default_files = gtk_rc_get_default_files();
205 if (STRINGP(gtkrc)) {
206 /* Found one, load it up! */
207 gchar **new_rc_files = NULL;
210 for (num_files = 0; default_files[num_files];
214 xnew_array_and_zero(gchar *, num_files + 3);
216 new_rc_files[0] = XSTRING_DATA(gtkrc);
217 for (ctr = 1; default_files[ctr - 1]; ctr++)
219 g_strdup(default_files[ctr - 1]);
221 gtk_rc_set_default_files(new_rc_files);
223 for (ctr = 1; new_rc_files[ctr]; ctr++) {
224 xfree(new_rc_files[ctr]);
230 Fgtk_init(Vgtk_initial_argv_list);
233 gdk_set_use_xshm(FALSE);
236 /* We attempt to load this file so that the user can set
237 ** gtk-initial-geometry and not need GNOME & session management to
238 ** set their default frame size. It also avoids the flicker
239 ** associated with setting the frame size in your .emacs file.
241 call4(Qload, build_string("~/.xemacs/gtk-options.el"), Qt, Qt, Qt);
243 #ifdef HAVE_GDK_IMLIB_INIT
244 /* Some themes in Gtk are so lame (most notably the Pixmap theme)
245 that they rely on gdk_imlib, but don't call its initialization
246 routines. This makes them USELESS for non-gnome applications.
247 So we bend over backwards to try and make them work. Losers. */
251 if (NILP(DEVICE_NAME(d)))
252 DEVICE_NAME(d) = display;
254 /* Always search for the best visual */
255 visual = gdk_visual_get_best();
256 cmap = gdk_colormap_new(visual, TRUE);
258 DEVICE_GTK_VISUAL(d) = visual;
259 DEVICE_GTK_COLORMAP(d) = cmap;
260 DEVICE_GTK_DEPTH(d) = visual->depth;
263 GtkWidget *w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
265 app_shell = gtk_xemacs_new(NULL);
266 gtk_container_add(GTK_CONTAINER(w), app_shell);
268 gtk_widget_realize(w);
271 DEVICE_GTK_APP_SHELL(d) = app_shell;
273 /* Realize the app_shell so that its window exists for GC creation
275 gtk_widget_realize(GTK_WIDGET(app_shell));
277 /* Need to set up some selection handlers */
278 gtk_selection_add_target(GTK_WIDGET(app_shell), GDK_SELECTION_PRIMARY,
279 GDK_SELECTION_TYPE_STRING, 0);
280 gtk_selection_add_target(GTK_WIDGET(app_shell),
281 gdk_atom_intern("CLIPBOARD", FALSE),
282 GDK_SELECTION_TYPE_STRING, 0);
284 gtk_signal_connect(GTK_OBJECT(app_shell), "selection_get",
285 GTK_SIGNAL_FUNC(emacs_gtk_selection_handle), NULL);
286 gtk_signal_connect(GTK_OBJECT(app_shell), "selection_clear_event",
288 (emacs_gtk_selection_clear_event_handle), NULL);
289 gtk_signal_connect(GTK_OBJECT(app_shell), "selection_received",
290 GTK_SIGNAL_FUNC(emacs_gtk_selection_received), NULL);
292 DEVICE_GTK_WM_COMMAND_FRAME(d) = Qnil;
294 gtk_init_modifier_mapping(d);
296 gtk_device_init_x_specific_cruft(d);
301 DEVICE_GTK_GC_CACHE(d) = make_gc_cache(GTK_WIDGET(app_shell));
302 DEVICE_GTK_GRAY_PIXMAP(d) = NULL;
304 gtk_init_device_class(d);
306 /* Run the elisp side of the X device initialization. */
307 call0(Qinit_pre_gtk_win);
310 static void gtk_finish_init_device(struct device *d, Lisp_Object props)
312 call0(Qinit_post_gtk_win);
315 static void gtk_mark_device(struct device *d)
317 mark_object(DEVICE_GTK_WM_COMMAND_FRAME(d));
318 mark_object(DEVICE_GTK_DATA(d)->x_keysym_map_hashtable);
321 /************************************************************************/
322 /* closing an X connection */
323 /************************************************************************/
325 static void free_gtk_device_struct(struct device *d)
327 xfree(d->device_data);
330 static void gtk_delete_device(struct device *d)
335 extern void (*__free_hook) ();
339 XSETDEVICE(device, d);
342 checking_free = (__free_hook != 0);
344 /* Disable strict free checking, to avoid bug in X library */
346 disable_strict_free_check();
349 free_gc_cache(DEVICE_GTK_GC_CACHE(d));
353 enable_strict_free_check();
357 if (EQ(device, Vdefault_gtk_device)) {
358 Lisp_Object devcons, concons;
359 /* #### handle deleting last X device */
360 Vdefault_gtk_device = Qnil;
361 DEVICE_LOOP_NO_BREAK(devcons, concons) {
362 if (DEVICE_GTK_P(XDEVICE(XCAR(devcons))) &&
363 !EQ(device, XCAR(devcons))) {
364 Vdefault_gtk_device = XCAR(devcons);
370 free_gtk_device_struct(d);
373 /************************************************************************/
374 /* handle X errors */
375 /************************************************************************/
377 const char *gtk_event_name(GdkEventType event_type)
379 GtkEnumValue *vals = gtk_type_enum_get_values(GTK_TYPE_GDK_EVENT_TYPE);
381 while (vals && (vals->value != event_type))
385 return (vals->value_nick);
390 /************************************************************************/
391 /* display information functions */
392 /************************************************************************/
394 DEFUN("default-gtk-device", Fdefault_gtk_device, 0, 0, 0, /*
395 Return the default GTK device for resourcing.
396 This is the first-created GTK device that still exists.
400 return Vdefault_gtk_device;
403 DEFUN("gtk-display-visual-class", Fgtk_display_visual_class, 0, 1, 0, /*
404 Return the visual class of the GTK display DEVICE is using.
405 The returned value will be one of the symbols `static-gray', `gray-scale',
406 `static-color', `pseudo-color', `true-color', or `direct-color'.
410 GdkVisual *vis = DEVICE_GTK_VISUAL(decode_gtk_device(device));
412 case GDK_VISUAL_STATIC_GRAY:
413 return intern("static-gray");
414 case GDK_VISUAL_GRAYSCALE:
415 return intern("gray-scale");
416 case GDK_VISUAL_STATIC_COLOR:
417 return intern("static-color");
418 case GDK_VISUAL_PSEUDO_COLOR:
419 return intern("pseudo-color");
420 case GDK_VISUAL_TRUE_COLOR:
421 return intern("true-color");
422 case GDK_VISUAL_DIRECT_COLOR:
423 return intern("direct-color");
425 error("display has an unknown visual class");
426 return Qnil; /* suppress compiler warning */
430 DEFUN("gtk-display-visual-depth", Fgtk_display_visual_depth, 0, 1, 0, /*
431 Return the bitplane depth of the visual the GTK display DEVICE is using.
435 return make_int(DEVICE_GTK_DEPTH(decode_gtk_device(device)));
439 gtk_device_system_metrics(struct device *d, enum device_metrics m)
443 gtk_widget_get_style(GTK_WIDGET(DEVICE_GTK_APP_SHELL(d)));
445 style = gtk_style_attach(style, w);
450 return Fcons(make_int(gdk_screen_width()),
451 make_int(gdk_screen_height()));
452 case DM_size_device_mm:
453 return Fcons(make_int(gdk_screen_width_mm()),
454 make_int(gdk_screen_height_mm()));
455 case DM_num_color_cells:
456 return make_int(gdk_colormap_get_system_size());
457 case DM_num_bit_planes:
458 return make_int(DEVICE_GTK_DEPTH(d));
461 case DM_color_default:
462 case DM_color_select:
463 case DM_color_balloon:
464 case DM_color_3d_face:
465 case DM_color_3d_light:
466 case DM_color_3d_dark:
468 case DM_color_menu_highlight:
469 case DM_color_menu_button:
470 case DM_color_menu_disabled:
471 case DM_color_toolbar:
472 case DM_color_scrollbar:
473 case DM_color_desktop:
474 case DM_color_workspace:
475 case DM_font_default:
476 case DM_font_menubar:
479 case DM_size_scrollbar:
481 case DM_size_toolbar:
482 case DM_size_toolbar_button:
483 case DM_size_toolbar_border:
485 case DM_size_icon_small:
486 case DM_size_workspace:
488 case DM_mouse_buttons:
489 case DM_swap_buttons:
494 default: /* No such device metric property for GTK devices */
499 DEFUN("gtk-keysym-on-keyboard-p", Fgtk_keysym_on_keyboard_p, 1, 2, 0, /*
500 Return true if KEYSYM names a key on the keyboard of DEVICE.
501 More precisely, return true if some keystroke (possibly including modifiers)
502 on the keyboard of DEVICE keys generates KEYSYM.
503 Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
504 /usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
505 The keysym name can be provided in two forms:
506 - if keysym is a string, it must be the name as known to X windows.
507 - if keysym is a symbol, it must be the name as known to SXEmacs.
508 The two names differ in capitalization and underscoring.
512 struct device *d = decode_device(device);
514 if (!DEVICE_GTK_P(d))
515 signal_simple_error("Not a GTK device", device);
519 (keysym, DEVICE_GTK_DATA(d)->x_keysym_map_hashtable,
523 /************************************************************************/
524 /* grabs and ungrabs */
525 /************************************************************************/
527 DEFUN("gtk-grab-pointer", Fgtk_grab_pointer, 0, 3, 0, /*
528 Grab the pointer and restrict it to its current window.
529 If optional DEVICE argument is nil, the default device will be used.
530 If optional CURSOR argument is non-nil, change the pointer shape to that
531 until `gtk-ungrab-pointer' is called (it should be an object returned by the
532 `make-cursor-glyph' function).
533 If the second optional argument IGNORE-KEYBOARD is non-nil, ignore all
534 keyboard events during the grab.
535 Returns t if the grab is successful, nil otherwise.
537 (device, cursor, ignore_keyboard))
541 struct device *d = decode_gtk_device(device);
544 CHECK_POINTER_GLYPH(cursor);
545 cursor = glyph_image_instance(cursor, device, ERROR_ME, 0);
548 /* We should call gdk_pointer_grab() and (possibly) gdk_keyboard_grab() here instead */
549 w = GET_GTK_WIDGET_WINDOW(FRAME_GTK_TEXT_WIDGET
550 (device_selected_frame(d)));
552 result = gdk_pointer_grab(w, FALSE, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK, w, NULL, /* #### BILL!!! Need to create a GdkCursor * as necessary! */
555 return (result == 0) ? Qt : Qnil;
558 DEFUN("gtk-ungrab-pointer", Fgtk_ungrab_pointer, 0, 1, 0, /*
559 Release a pointer grab made with `gtk-grab-pointer'.
560 If optional first arg DEVICE is nil the default device is used.
561 If it is t the pointer will be released on all GTK devices.
565 if (!EQ(device, Qt)) {
566 gdk_pointer_ungrab(GDK_CURRENT_TIME);
568 Lisp_Object devcons, concons;
570 DEVICE_LOOP_NO_BREAK(devcons, concons) {
571 struct device *d = XDEVICE(XCAR(devcons));
574 gdk_pointer_ungrab(GDK_CURRENT_TIME);
580 DEFUN("gtk-grab-keyboard", Fgtk_grab_keyboard, 0, 1, 0, /*
581 Grab the keyboard on the given device (defaulting to the selected one).
582 So long as the keyboard is grabbed, all keyboard events will be delivered
583 to emacs -- it is not possible for other clients to eavesdrop on them.
584 Ungrab the keyboard with `gtk-ungrab-keyboard' (use an unwind-protect).
585 Returns t if the grab is successful, nil otherwise.
589 struct device *d = decode_gtk_device(device);
591 GET_GTK_WIDGET_WINDOW(FRAME_GTK_TEXT_WIDGET
592 (device_selected_frame(d)));
594 gdk_keyboard_grab(w, FALSE, GDK_CURRENT_TIME);
599 DEFUN("gtk-ungrab-keyboard", Fgtk_ungrab_keyboard, 0, 1, 0, /*
600 Release a keyboard grab made with `gtk-grab-keyboard'.
604 gdk_keyboard_ungrab(GDK_CURRENT_TIME);
608 /************************************************************************/
610 /************************************************************************/
611 DEFUN("gtk-style-info", Fgtk_style_info, 0, 1, 0, /*
612 Get the style information for a Gtk device.
616 struct device *d = decode_device(device);
617 GtkStyle *style = NULL;
618 Lisp_Object result = Qnil;
619 GtkWidget *app_shell = GTK_WIDGET(DEVICE_GTK_APP_SHELL(d));
620 GdkWindow *w = GET_GTK_WIDGET_WINDOW(app_shell);
622 if (!DEVICE_GTK_P(d))
625 style = gtk_widget_get_style(app_shell);
626 style = gtk_style_attach(style, w);
631 #define FROB_COLOR(slot, name) \
632 result = nconc2 (result, \
633 list2 (intern (name), \
634 list5 (xemacs_gtk_convert_color (&style->slot[GTK_STATE_NORMAL], app_shell),\
635 xemacs_gtk_convert_color (&style->slot[GTK_STATE_ACTIVE], app_shell),\
636 xemacs_gtk_convert_color (&style->slot[GTK_STATE_PRELIGHT], app_shell),\
637 xemacs_gtk_convert_color (&style->slot[GTK_STATE_SELECTED], app_shell),\
638 xemacs_gtk_convert_color (&style->slot[GTK_STATE_INSENSITIVE], app_shell))))
640 FROB_COLOR(fg, "foreground");
641 FROB_COLOR(bg, "background");
642 FROB_COLOR(light, "light");
643 FROB_COLOR(dark, "dark");
644 FROB_COLOR(mid, "mid");
645 FROB_COLOR(text, "text");
646 FROB_COLOR(base, "base");
649 result = nconc2(result, list2(Qfont, convert_font(style->font)));
651 #define FROB_PIXMAP(state) (style->rc_style->bg_pixmap_name[state] ? build_string (style->rc_style->bg_pixmap_name[state]) : Qnil)
654 result = nconc2(result, list2(Qbackground,
660 (GTK_STATE_PRELIGHT),
662 (GTK_STATE_SELECTED),
664 (GTK_STATE_INSENSITIVE))));
670 /************************************************************************/
672 /************************************************************************/
674 void syms_of_device_gtk(void)
676 DEFSUBR(Fdefault_gtk_device);
677 DEFSUBR(Fgtk_keysym_on_keyboard_p);
678 DEFSUBR(Fgtk_display_visual_class);
679 DEFSUBR(Fgtk_display_visual_depth);
680 DEFSUBR(Fgtk_style_info);
681 DEFSUBR(Fgtk_grab_pointer);
682 DEFSUBR(Fgtk_ungrab_pointer);
683 DEFSUBR(Fgtk_grab_keyboard);
684 DEFSUBR(Fgtk_ungrab_keyboard);
687 defsymbol(&Qinit_pre_gtk_win, "init-pre-gtk-win");
688 defsymbol(&Qinit_post_gtk_win, "init-post-gtk-win");
691 void console_type_create_device_gtk(void)
693 CONSOLE_HAS_METHOD(gtk, init_device);
694 CONSOLE_HAS_METHOD(gtk, finish_init_device);
695 CONSOLE_HAS_METHOD(gtk, mark_device);
696 CONSOLE_HAS_METHOD(gtk, delete_device);
697 CONSOLE_HAS_METHOD(gtk, device_system_metrics);
698 /* CONSOLE_IMPLEMENTATION_FLAGS (gtk, XDEVIMPF_PIXEL_GEOMETRY); */
699 /* I inserted the above commented out statement, as the original
700 implementation of gtk_device_implementation_flags(), which I
701 deleted, contained commented out XDEVIMPF_PIXEL_GEOMETRY - kkm */
704 void vars_of_device_gtk(void)
708 staticpro(&Vdefault_gtk_device);
710 DEFVAR_LISP("gtk-initial-argv-list", &Vgtk_initial_argv_list /*
711 You don't want to know.
712 This is used during startup to communicate the remaining arguments in
713 `command-line-args-left' to the C code, which passes the args to
714 the GTK initialization code, which removes some args, and then the
715 args are placed back into `gtk-initial-arg-list' and thence into
716 `command-line-args-left'. Perhaps `command-line-args-left' should
720 DEFVAR_LISP("gtk-initial-geometry", &Vgtk_initial_geometry /*
721 You don't want to know.
722 This is used during startup to communicate the default geometry to GTK.
725 Vdefault_gtk_device = Qnil;
726 Vgtk_initial_geometry = Qnil;
727 Vgtk_initial_argv_list = Qnil;
730 #include <gdk/gdkx.h>
731 static void gtk_device_init_x_specific_cruft(struct device *d)
733 DEVICE_INFD(d) = DEVICE_OUTFD(d) = ConnectionNumber(GDK_DISPLAY());