1 /* Generic device functions.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995, 1996 Ben Wing
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: Not in FSF. */
24 /* Original version by Chuck Thompson;
25 rewritten and expanded by Ben Wing. */
34 #include "events/events.h"
38 #include "redisplay.h"
39 #include "specifier.h"
43 #ifdef HAVE_SCROLLBARS
44 #include "scrollbar.h"
47 #include "syssignal.h"
49 /* Vdefault_device is the firstly-created non-stream device that's still
50 around. We don't really use it anywhere currently, but it might
51 be used for resourcing at some point. (Currently we use
52 Vdefault_x_device.) */
53 Lisp_Object Vdefault_device;
55 Lisp_Object Vcreate_device_hook, Vdelete_device_hook;
58 /* Qcolor defined in general.c */
59 Lisp_Object Qgrayscale, Qmono;
61 /* Device metrics symbols */
63 Qcolor_default, Qcolor_select, Qcolor_balloon, Qcolor_3d_face,
64 Qcolor_3d_light, Qcolor_3d_dark, Qcolor_menu, Qcolor_menu_highlight,
65 Qcolor_menu_button, Qcolor_menu_disabled, Qcolor_toolbar,
66 Qcolor_scrollbar, Qcolor_desktop, Qcolor_workspace, Qfont_default,
67 Qfont_menubar, Qfont_dialog, Qsize_cursor, Qsize_scrollbar,
68 Qsize_menu, Qsize_toolbar, Qsize_toolbar_button,
69 Qsize_toolbar_border, Qsize_icon, Qsize_icon_small, Qsize_device,
70 Qsize_workspace, Qoffset_workspace, Qsize_device_mm, Qdevice_dpi,
71 Qnum_bit_planes, Qnum_color_cells, Qmouse_buttons, Qswap_buttons,
72 Qshow_sounds, Qslow_device, Qsecurity;
74 Lisp_Object Qdevicep, Qdevice_live_p;
75 Lisp_Object Qcreate_device_hook;
76 Lisp_Object Qdelete_device_hook;
77 Lisp_Object Vdevice_class_list;
79 static Lisp_Object mark_device(Lisp_Object obj)
81 struct device *d = XDEVICE(obj);
84 mark_object(d->connection);
85 mark_object(d->canon_connection);
86 mark_object(d->console);
87 mark_object(d->selected_frame);
88 mark_object(d->frame_with_focus_real);
89 mark_object(d->frame_with_focus_for_hooks);
90 mark_object(d->frame_that_ought_to_have_focus);
91 mark_object(d->device_class);
92 mark_object(d->user_defined_tags);
93 mark_object(d->pixel_to_glyph_cache.obj1);
94 mark_object(d->pixel_to_glyph_cache.obj2);
96 mark_object(d->color_instance_cache);
97 mark_object(d->font_instance_cache);
99 mark_object(d->charset_font_cache);
101 mark_object(d->image_instance_cache);
104 mark_object(d->devmeths->symbol);
105 MAYBE_DEVMETH(d, mark_device, (d));
108 return (d->frame_list);
112 print_device(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
114 struct device *d = XDEVICE(obj);
117 error("printing unreadable object #<device %s 0x%x>",
118 XSTRING_DATA(d->name), d->header.uid);
120 write_fmt_string(printcharfun, "#<%s-device",
121 (!DEVICE_LIVE_P(d) ? "dead" :DEVICE_TYPE_NAME(d)));
122 if (DEVICE_LIVE_P(d) && !NILP(DEVICE_CONNECTION(d))) {
123 write_c_string(" on ", printcharfun);
124 print_internal(DEVICE_CONNECTION(d), printcharfun, 1);
126 write_fmt_str(printcharfun, " 0x%x>", d->header.uid);
129 DEFINE_LRECORD_IMPLEMENTATION("device", device,
130 mark_device, print_device, 0, 0, 0, 0,
133 int valid_device_class_p(Lisp_Object class)
135 return !NILP(memq_no_quit(class, Vdevice_class_list));
138 DEFUN("valid-device-class-p", Fvalid_device_class_p, 1, 1, 0, /*
139 Given a DEVICE-CLASS, return t if it is valid.
140 Valid classes are 'color, 'grayscale, and 'mono.
144 return valid_device_class_p(device_class) ? Qt : Qnil;
147 DEFUN("device-class-list", Fdevice_class_list, 0, 0, 0, /*
148 Return a list of valid device classes.
152 return Fcopy_sequence(Vdevice_class_list);
155 static struct device *allocate_device(Lisp_Object console)
158 struct device *d = alloc_lcrecord_type(struct device, &lrecord_device);
163 XSETDEVICE(device, d);
167 d->console = console;
168 d->connection = Qnil;
169 d->canon_connection = Qnil;
170 d->frame_list = Qnil;
171 d->selected_frame = Qnil;
172 d->frame_with_focus_real = Qnil;
173 d->frame_with_focus_for_hooks = Qnil;
174 d->frame_that_ought_to_have_focus = Qnil;
175 d->device_class = Qnil;
176 d->user_defined_tags = Qnil;
177 d->pixel_to_glyph_cache.obj1 = Qnil;
178 d->pixel_to_glyph_cache.obj2 = Qnil;
180 d->infd = d->outfd = -1;
182 /* #### is 20 reasonable? */
183 d->color_instance_cache =
184 make_lisp_hash_table(20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQUAL);
185 d->font_instance_cache =
186 make_lisp_hash_table(20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQUAL);
188 /* Note that the following table is bi-level. */
189 d->charset_font_cache =
190 make_lisp_hash_table(20, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
193 Note that the image instance cache is actually bi-level.
194 See device.h. We use a low number here because most of the
195 time there aren't very many different masks that will be used.
197 d->image_instance_cache =
198 make_lisp_hash_table(5, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
204 struct device *decode_device(Lisp_Object device)
207 device = Fselected_device(Qnil);
208 /* quietly accept frames for the device arg */
209 else if (FRAMEP(device))
210 device = FRAME_DEVICE(decode_frame(device));
211 CHECK_LIVE_DEVICE(device);
212 return XDEVICE(device);
215 DEFUN("dfw-device", Fdfw_device, 1, 1, 0, /*
216 Given a device, frame, or window, return the associated device.
217 Return nil otherwise.
221 return DFW_DEVICE(object);
224 DEFUN("selected-device", Fselected_device, 0, 1, 0, /*
225 Return the device which is currently active.
226 If optional CONSOLE is non-nil, return the device that would be currently
227 active if CONSOLE were the selected console.
231 if (NILP(console) && NILP(Vselected_console))
232 return Qnil; /* happens early in temacs */
233 return CONSOLE_SELECTED_DEVICE(decode_console(console));
236 /* Called from selected_frame_1(), called from Fselect_window() */
237 void select_device_1(Lisp_Object device)
239 struct device *dev = XDEVICE(device);
240 Lisp_Object old_selected_device = Fselected_device(Qnil);
242 if (EQ(device, old_selected_device))
245 /* now select the device's console */
246 CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(dev))) = device;
247 select_console_1(DEVICE_CONSOLE(dev));
250 DEFUN("select-device", Fselect_device, 1, 1, 0, /*
251 Select the device DEVICE.
252 Subsequent editing commands apply to its console, selected frame,
254 The selection of DEVICE lasts until the next time the user does
255 something to select a different device, or until the next time this
260 CHECK_LIVE_DEVICE(device);
262 /* select the device's selected frame's selected window. This will call
263 selected_frame_1()->selected_device_1()->selected_console_1(). */
264 if (!NILP(DEVICE_SELECTED_FRAME(XDEVICE(device))))
265 Fselect_window(FRAME_SELECTED_WINDOW
266 (XFRAME(DEVICE_SELECTED_FRAME(XDEVICE(device)))),
269 error("Can't select a device with no frames");
273 void set_device_selected_frame(struct device *d, Lisp_Object frame)
275 if (!NILP(frame) && !FRAME_MINIBUF_ONLY_P(XFRAME(frame)))
276 set_console_last_nonminibuf_frame(XCONSOLE(DEVICE_CONSOLE(d)),
278 d->selected_frame = frame;
281 DEFUN("set-device-selected-frame", Fset_device_selected_frame, 2, 2, 0, /*
282 Set the selected frame of device object DEVICE to FRAME.
283 If DEVICE is nil, the selected device is used.
284 If DEVICE is the selected device, this makes FRAME the selected frame.
288 XSETDEVICE(device, decode_device(device));
289 CHECK_LIVE_FRAME(frame);
291 if (!EQ(device, FRAME_DEVICE(XFRAME(frame))))
292 error("In `set-device-selected-frame', FRAME is not on DEVICE");
294 if (EQ(device, Fselected_device(Qnil)))
295 return Fselect_frame(frame);
297 set_device_selected_frame(XDEVICE(device), frame);
301 DEFUN("devicep", Fdevicep, 1, 1, 0, /*
302 Return non-nil if OBJECT is a device.
306 return DEVICEP(object) ? Qt : Qnil;
309 DEFUN("device-live-p", Fdevice_live_p, 1, 1, 0, /*
310 Return non-nil if OBJECT is a device that has not been deleted.
314 return DEVICEP(object) && DEVICE_LIVE_P(XDEVICE(object)) ? Qt : Qnil;
317 DEFUN("device-name", Fdevice_name, 0, 1, 0, /*
318 Return the name of the specified device.
319 DEVICE defaults to the selected device if omitted.
323 return DEVICE_NAME(decode_device(device));
326 DEFUN("device-connection", Fdevice_connection, 0, 1, 0, /*
327 Return the connection of the specified device.
328 DEVICE defaults to the selected device if omitted.
332 return DEVICE_CONNECTION(decode_device(device));
335 DEFUN("device-console", Fdevice_console, 0, 1, 0, /*
336 Return the console of the specified device.
337 DEVICE defaults to the selected device if omitted.
341 return DEVICE_CONSOLE(decode_device(device));
344 #ifdef HAVE_WINDOW_SYSTEM
346 static void init_global_resources(struct device *d)
348 init_global_faces(d);
349 #ifdef HAVE_SCROLLBARS
350 init_global_scrollbars(d);
353 init_global_toolbars(d);
359 static void init_device_resources(struct device *d)
361 init_device_faces(d);
362 #ifdef HAVE_SCROLLBARS
363 init_device_scrollbars(d);
366 init_device_toolbars(d);
371 semi_canonicalize_device_connection(struct console_methods *meths,
372 Lisp_Object name, Error_behavior errb)
374 if (HAS_CONTYPE_METH_P(meths, semi_canonicalize_device_connection))
375 return CONTYPE_METH(meths, semi_canonicalize_device_connection,
378 return CONTYPE_METH_OR_GIVEN(meths,
379 canonicalize_device_connection,
384 canonicalize_device_connection(struct console_methods *meths,
385 Lisp_Object name, Error_behavior errb)
387 if (HAS_CONTYPE_METH_P(meths, canonicalize_device_connection))
388 return CONTYPE_METH(meths, canonicalize_device_connection,
391 return CONTYPE_METH_OR_GIVEN(meths,
392 semi_canonicalize_device_connection,
397 find_device_of_type(struct console_methods *meths, Lisp_Object canon)
399 Lisp_Object devcons, concons;
401 DEVICE_LOOP_NO_BREAK(devcons, concons) {
402 Lisp_Object device = XCAR(devcons);
404 if (EQ(CONMETH_TYPE(meths), DEVICE_TYPE(XDEVICE(device)))
405 && internal_equal(DEVICE_CANON_CONNECTION(XDEVICE(device)),
413 DEFUN("find-device", Ffind_device, 1, 2, 0, /*
414 Look for an existing device attached to connection CONNECTION.
415 Return the device if found; otherwise, return nil.
417 If TYPE is specified, only return devices of that type; otherwise,
418 return devices of any type. (It is possible, although unlikely,
419 that two devices of different types could have the same connection
420 name; in such a case, the first device found is returned.)
424 Lisp_Object canon = Qnil;
430 struct console_methods *conmeths =
431 decode_console_type(type, ERROR_ME);
433 canonicalize_device_connection(conmeths, connection,
436 RETURN_UNGCPRO(Qnil);
438 RETURN_UNGCPRO(find_device_of_type(conmeths, canon));
442 for (i = 0; i < Dynarr_length(the_console_type_entry_dynarr);
444 struct console_methods *conmeths =
445 Dynarr_at(the_console_type_entry_dynarr, i).meths;
447 canonicalize_device_connection(conmeths, connection,
449 if (!UNBOUNDP(canon)) {
451 find_device_of_type(conmeths, canon);
453 RETURN_UNGCPRO(device);
457 RETURN_UNGCPRO(Qnil);
461 DEFUN("get-device", Fget_device, 1, 2, 0, /*
462 Look for an existing device attached to connection CONNECTION.
463 Return the device if found; otherwise, signal an error.
465 If TYPE is specified, only return devices of that type; otherwise,
466 return devices of any type. (It is possible, although unlikely,
467 that two devices of different types could have the same connection
468 name; in such a case, the first device found is returned.)
472 Lisp_Object device = Ffind_device(connection, type);
475 signal_simple_error("No such device", connection);
477 signal_simple_error_2("No such device", type,
483 static Lisp_Object delete_deviceless_console(Lisp_Object console)
485 if (NILP(XCONSOLE(console)->device_list))
486 Fdelete_console(console, Qnil);
490 DEFUN("make-device", Fmake_device, 2, 3, 0, /*
491 Return a new device of type TYPE, attached to connection CONNECTION.
493 The valid values for CONNECTION are device-specific; however,
494 CONNECTION is generally a string. (Specifically, for X devices,
495 CONNECTION should be a display specification such as "foo:0", and
496 for TTY devices, CONNECTION should be the filename of a TTY device
497 file, such as "/dev/ttyp4", or nil to refer to SXEmacs' standard
500 PROPS, if specified, should be a plist of properties controlling
503 If CONNECTION specifies an already-existing device connection, that
504 device is simply returned; no new device is created, and PROPS
507 (type, connection, props))
509 /* This function can GC */
512 Lisp_Object device = Qnil;
513 Lisp_Object console = Qnil;
514 Lisp_Object name = Qnil;
515 struct console_methods *conmeths;
516 int speccount = specpdl_depth();
518 struct gcpro gcpro1, gcpro2, gcpro3;
519 #ifdef HAVE_X_WINDOWS
520 /* #### icky-poo. If this is the first X device we are creating,
521 then retrieve the global face resources. We have to do it
522 here, at the same time as (or just before) the device face
523 resources are retrieved; specifically, it needs to be done
524 after the device has been created but before any frames have
525 been popped up or much anything else has been done. It's
526 possible for other devices to specify different global
527 resources (there's a property on each X server's root window
528 that holds some resources); tough luck for the moment.
530 This is a nasty violation of device independence, but
531 there's not a whole lot I can figure out to do about it.
532 The real problem is that the concept of resources is not
533 generalized away from X. Similar resource-related
534 device-independence violations occur in faces.el. */
535 int first_x_device = NILP(Vdefault_x_device) && EQ(type, Qx);
538 int first_gtk_device = NILP(Vdefault_gtk_device) && EQ(type, Qgtk);
541 GCPRO3(device, console, name);
543 conmeths = decode_console_type(type, ERROR_ME_NOT);
545 signal_simple_error("Invalid device type", type);
547 device = Ffind_device(connection, type);
549 RETURN_UNGCPRO(device);
551 name = Fplist_get(props, Qname, Qnil);
554 Lisp_Object conconnect =
555 (HAS_CONTYPE_METH_P(conmeths, device_to_console_connection))
556 ? CONTYPE_METH(conmeths, device_to_console_connection,
557 (connection, ERROR_ME)) : connection;
558 console = create_console(name, type, conconnect, props);
561 record_unwind_protect(delete_deviceless_console, console);
563 con = XCONSOLE(console);
564 d = allocate_device(console);
565 XSETDEVICE(device, d);
567 d->devmeths = con->conmeths;
569 DEVICE_NAME(d) = name;
570 DEVICE_CONNECTION(d) =
571 semi_canonicalize_device_connection(conmeths, connection, ERROR_ME);
572 DEVICE_CANON_CONNECTION(d) =
573 canonicalize_device_connection(conmeths, connection, ERROR_ME);
575 MAYBE_DEVMETH(d, init_device, (d, props));
577 /* Do it this way so that the device list is in order of creation */
578 con->device_list = nconc2(con->device_list, Fcons(device, Qnil));
579 RESET_CHANGED_SET_FLAGS;
580 if (NILP(Vdefault_device) || DEVICE_STREAM_P(XDEVICE(Vdefault_device)))
581 Vdefault_device = device;
583 #ifdef HAVE_X_WINDOWS
585 init_global_resources(d);
588 if (first_gtk_device)
589 init_global_resources(d);
591 init_device_resources(d);
593 MAYBE_DEVMETH(d, finish_init_device, (d, props));
595 /* If this is the first device on the console, make it the selected one. */
596 if (NILP(CONSOLE_SELECTED_DEVICE(con)))
597 CONSOLE_SELECTED_DEVICE(con) = device;
599 /* #### the following should trap errors. */
600 setup_device_initial_specifier_tags(d);
603 unbind_to(speccount, Qnil);
607 /* find a device other than the selected one. Prefer non-stream
608 devices over stream devices. Maybe stay on the same console. */
610 static Lisp_Object find_other_device(Lisp_Object device, int on_same_console)
612 Lisp_Object devcons = Qnil, concons;
613 Lisp_Object console = DEVICE_CONSOLE(XDEVICE(device));
615 /* look for a non-stream device */
616 DEVICE_LOOP_NO_BREAK(devcons, concons) {
617 Lisp_Object dev = XCAR(devcons);
619 && !EQ(console, DEVICE_CONSOLE(XDEVICE(dev))))
621 if (!DEVICE_STREAM_P(XDEVICE(dev)) && !EQ(dev, device) &&
622 !NILP(DEVICE_SELECTED_FRAME(XDEVICE(dev))))
628 return XCAR(devcons);
630 /* OK, now look for a stream device */
631 DEVICE_LOOP_NO_BREAK(devcons, concons) {
632 Lisp_Object dev = XCAR(devcons);
634 && !EQ(console, DEVICE_CONSOLE(XDEVICE(dev))))
637 && !NILP(DEVICE_SELECTED_FRAME(XDEVICE(dev))))
642 return XCAR(devcons);
644 /* Sorry, there ain't none */
649 find_nonminibuffer_frame_not_on_device_predicate(Lisp_Object frame,
654 VOID_TO_LISP(device, closure);
655 if (FRAME_MINIBUF_ONLY_P(XFRAME(frame)))
657 if (EQ(device, FRAME_DEVICE(XFRAME(frame))))
662 Lisp_Object find_nonminibuffer_frame_not_on_device(Lisp_Object device)
664 return find_some_frame(find_nonminibuffer_frame_not_on_device_predicate,
665 LISP_TO_VOID(device));
670 If FORCE is non-zero, allow deletion of the only frame.
672 If CALLED_FROM_DELETE_CONSOLE is non-zero, then, if
673 deleting the last device on a console, just delete it,
674 instead of calling `delete-console'.
676 If FROM_IO_ERROR is non-zero, then the device is gone due
677 to an I/O error. This affects what happens if we exit
678 (we do an emergency exit instead of `save-buffers-kill-emacs'.)
682 delete_device_internal(struct device *d, int force,
683 int called_from_delete_console, int from_io_error)
685 /* This function can GC */
690 /* OK to delete an already-deleted device. */
691 if (!DEVICE_LIVE_P(d))
694 XSETDEVICE(device, d);
697 c = XCONSOLE(DEVICE_CONSOLE(d));
699 if (!called_from_delete_console) {
700 int delete_console = 0;
701 /* If we're deleting the only device on the console,
702 delete the console. */
703 if ((XINT(Flength(CONSOLE_DEVICE_LIST(c))) == 1)
704 /* if we just created the device, it might not be listed,
706 && !NILP(memq_no_quit(device, CONSOLE_DEVICE_LIST(c))))
708 /* Or if there aren't any nonminibuffer frames that would be
709 left, delete the console (this will make SXEmacs exit). */
710 else if (NILP(find_nonminibuffer_frame_not_on_device(device)))
713 if (delete_console) {
714 delete_console_internal(c, force, 0, from_io_error);
725 /* First delete all frames without their own minibuffers,
726 to avoid errors coming from attempting to delete a frame
727 that is a surrogate for another frame. */
728 DEVICE_FRAME_LOOP(frmcons, d) {
729 struct frame *f = XFRAME(XCAR(frmcons));
730 /* delete_frame_internal() might do anything such as run hooks,
732 if (FRAME_LIVE_P(f) && !FRAME_HAS_MINIBUF_P(f))
733 delete_frame_internal(f, 1, 1, from_io_error);
735 if (!DEVICE_LIVE_P(d)) { /* make sure the delete-*-hook didn't
736 go ahead and delete anything */
742 /* #### This should probably be a device method but it is time for
743 19.14 to go out the door. */
744 /* #### BILL!!! Should this deal with HAVE_MSWINDOWS as well? */
745 #if defined (HAVE_X_WINDOWS) || defined (HAVE_GTK)
746 /* Next delete all frames which have the popup property to avoid
747 deleting a child after its parent. */
748 DEVICE_FRAME_LOOP(frmcons, d) {
749 struct frame *f = XFRAME(XCAR(frmcons));
751 if (FRAME_LIVE_P(f)) {
753 Fframe_property(XCAR(frmcons), Qpopup,
756 delete_frame_internal(f, 1, 1,
759 if (!DEVICE_LIVE_P(d)) { /* make sure the delete-*-hook didn't
760 go ahead and delete anything */
766 #endif /* HAVE_X_WINDOWS */
768 DEVICE_FRAME_LOOP(frmcons, d) {
769 struct frame *f = XFRAME(XCAR(frmcons));
770 /* delete_frame_internal() might do anything such as run hooks,
773 delete_frame_internal(f, 1, 1, from_io_error);
775 if (!DEVICE_LIVE_P(d)) { /* make sure the delete-*-hook didn't
776 go ahead and delete anything */
783 set_device_selected_frame(d, Qnil);
785 /* try to select another device */
787 if (EQ(device, Fselected_device(DEVICE_CONSOLE(d)))) {
788 Lisp_Object other_dev = find_other_device(device, 1);
789 if (!NILP(other_dev))
790 Fselect_device(other_dev);
793 if (EQ(device, Vdefault_device))
794 Vdefault_device = find_other_device(device, 0);
796 MAYBE_DEVMETH(d, delete_device, (d));
798 CONSOLE_DEVICE_LIST(c) = delq_no_quit(device, CONSOLE_DEVICE_LIST(c));
799 RESET_CHANGED_SET_FLAGS;
800 d->devmeths = dead_console_methods;
804 /* delete a device as a result of an I/O error. Called from
805 an enqueued magic-eval event. */
807 void io_error_delete_device(Lisp_Object device)
809 /* Note: it's the console that should get deleted, but
810 delete_device_internal() contains a hack that also deletes the
811 console when called from this function. */
812 delete_device_internal(XDEVICE(device), 1, 0, 1);
815 DEFUN("delete-device", Fdelete_device, 1, 2, 0, /*
816 Delete DEVICE, permanently eliminating it from use.
817 Normally, you cannot delete the last non-minibuffer-only frame (you must
818 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
819 second argument FORCE is non-nil, you can delete the last frame. (This
820 will automatically call `save-buffers-kill-emacs'.)
824 CHECK_DEVICE(device);
825 delete_device_internal(XDEVICE(device), !NILP(force), 0, 0);
829 DEFUN("device-frame-list", Fdevice_frame_list, 0, 1, 0, /*
830 Return a list of all frames on DEVICE.
831 If DEVICE is nil, the selected device will be used.
835 return Fcopy_sequence(DEVICE_FRAME_LIST(decode_device(device)));
838 DEFUN("device-class", Fdevice_class, 0, 1, 0, /*
839 Return the class (color behavior) of DEVICE.
840 This will be one of 'color, 'grayscale, or 'mono.
844 return DEVICE_CLASS(decode_device(device));
847 DEFUN("set-device-class", Fset_device_class, 2, 2, 0, /*
848 Set the class (color behavior) of DEVICE.
849 CLASS should be one of 'color, 'grayscale, or 'mono.
850 This is only allowed on device such as TTY devices, where the color
851 behavior cannot necessarily be determined automatically.
855 struct device *d = decode_device(device);
856 XSETDEVICE(device, d);
857 if (!DEVICE_TTY_P(d))
858 signal_simple_error("Cannot change the class of this device",
860 if (!EQ(class, Qcolor) && !EQ(class, Qmono) && !EQ(class, Qgrayscale))
861 signal_simple_error("Must be color, mono, or grayscale", class);
862 if (!EQ(DEVICE_CLASS(d), class)) {
864 DEVICE_CLASS(d) = class;
865 DEVICE_FRAME_LOOP(frmcons, d) {
866 struct frame *f = XFRAME(XCAR(frmcons));
868 recompute_all_cached_specifiers_in_frame(f);
869 MARK_FRAME_FACES_CHANGED(f);
870 MARK_FRAME_GLYPHS_CHANGED(f);
871 MARK_FRAME_SUBWINDOWS_CHANGED(f);
872 MARK_FRAME_TOOLBARS_CHANGED(f);
873 MARK_FRAME_GUTTERS_CHANGED(f);
874 f->menubar_changed = 1;
880 DEFUN("set-device-baud-rate", Fset_device_baud_rate, 2, 2, 0, /*
881 Set the output baud rate of DEVICE to RATE.
882 On most systems, changing this value will affect the amount of padding
883 and other strategic decisions made during redisplay.
889 DEVICE_BAUD_RATE(decode_device(device)) = XINT(rate);
894 DEFUN("device-baud-rate", Fdevice_baud_rate, 0, 1, 0, /*
895 Return the output baud rate of DEVICE.
899 return make_int(DEVICE_BAUD_RATE(decode_device(device)));
902 DEFUN("device-printer-p", Fdevice_printer_p, 0, 1, 0, /*
903 Return t if DEVICE is a printer, nil if it is a display. DEVICE defaults
904 to selected device if omitted, and must be live if specified.
908 return DEVICE_PRINTER_P(decode_device(device)) ? Qt : Qnil;
911 DEFUN("device-system-metric", Fdevice_system_metric, 1, 3, 0, /*
912 Get a metric for DEVICE as provided by the system.
914 METRIC must be a symbol specifying requested metric. Note that the metrics
915 returned are these provided by the system internally, not read from resources,
916 so obtained from the most internal level.
918 If a metric is not provided by the system, then DEFAULT is returned.
920 When DEVICE is nil, selected device is assumed
922 Metrics, by group, are:
924 COLORS. Colors are returned as valid color instantiators. No other assumption
925 on the returned value should be made (i.e. it can be a string on one system but
926 a color instance on another). For colors, returned value is a cons of
927 foreground and background colors. Note that if the system provides only one
928 color of the pair, the second one may be nil.
930 color-default Standard window text foreground and background.
931 color-select Selection highlight text and background colors.
932 color-balloon Balloon popup text and background colors.
933 color-3d-face 3-D object (button, modeline) text and surface colors.
934 color-3d-light Fore and back colors for 3-D edges facing light source.
935 color-3d-dark Fore and back colors for 3-D edges facing away from
937 color-menu Text and background for menus
938 color-menu-highlight Selected menu item colors
939 color-menu-button Menu button colors
940 color-menu-disabled Unselectable menu item colors
941 color-toolbar Toolbar foreground and background colors
942 color-scrollbar Scrollbar foreground and background colors
943 color-desktop Desktop window colors
944 color-workspace Workspace window colors
946 FONTS. Fonts are returned as valid font instantiators. No other assumption on
947 the returned value should be made (i.e. it can be a string on one system but
948 font instance on another).
950 font-default Default fixed width font.
951 font-menubar Menubar font
952 font-dialog Dialog boxes font
954 GEOMETRY. These metrics are returned as conses of (X . Y). As with colors,
955 either car or cdr of the cons may be nil if the system does not provide one
956 of the corresponding dimensions.
958 size-cursor Mouse cursor size.
959 size-scrollbar Scrollbars (WIDTH . HEIGHT)
960 size-menu Menubar height, as (nil . HEIGHT)
961 size-toolbar Toolbar width and height.
962 size-toolbar-button Toolbar button size.
963 size-toolbar-border Toolbar border width and height.
964 size-icon Icon dimensions.
965 size-icon-small Small icon dimensions.
966 size-device Device screen or paper size in pixels.
967 size-workspace Workspace size in pixels. This can be less than or
968 equal to the above. For displays, this is the area
969 available to applications less window manager
970 decorations. For printers, this is the size of
972 offset-workspace Offset of workspace area from the top left corner
973 of screen or paper, in pixels.
974 size-device-mm Device screen size in millimeters.
975 device-dpi Device resolution, in dots per inch.
976 num-bit-planes Integer, number of device bit planes.
977 num-color-cells Integer, number of device color cells.
979 FEATURES. This group reports various device features. If a feature is
980 present, integer 1 (one) is returned, if it is not present, then integer
981 0 (zero) is returned. If the system is unaware of the feature, then
984 mouse-buttons Integer, number of mouse buttons, or zero if no mouse.
985 swap-buttons Non-zero if left and right mouse buttons are swapped.
986 show-sounds User preference for visual over audible bell.
987 slow-device Device is slow, avoid animation.
988 security Non-zero if user environment is secure.
990 (device, metric, default_))
992 struct device *d = decode_device(device);
993 enum device_metrics m;
998 else if (EQ (metric, Q##met)) \
1002 FROB(color_default);
1004 FROB(color_balloon);
1005 FROB(color_3d_face);
1006 FROB(color_3d_light);
1007 FROB(color_3d_dark);
1009 FROB(color_menu_highlight);
1010 FROB(color_menu_button);
1011 FROB(color_menu_disabled);
1012 FROB(color_toolbar);
1013 FROB(color_scrollbar);
1014 FROB(color_desktop);
1015 FROB(color_workspace);
1020 FROB(size_scrollbar);
1023 FROB(size_toolbar_button);
1024 FROB(size_toolbar_border);
1026 FROB(size_icon_small);
1028 FROB(size_workspace);
1029 FROB(offset_workspace);
1030 FROB(size_device_mm);
1032 FROB(num_bit_planes);
1033 FROB(num_color_cells);
1034 FROB(mouse_buttons);
1040 signal_simple_error("Invalid device metric symbol", metric);
1042 res = DEVMETH_OR_GIVEN(d, device_system_metrics, (d, m), Qunbound);
1043 return UNBOUNDP(res) ? default_ : res;
1048 DEFUN("device-system-metrics", Fdevice_system_metrics, 0, 1, 0, /*
1049 Get a property list of device metric for DEVICE.
1051 See `device-system-metric' for the description of available metrics.
1052 DEVICE defaults to selected device when omitted.
1056 struct device *d = decode_device(device);
1057 Lisp_Object plist = Qnil, one_metric;
1060 if (!UNBOUNDP ((one_metric = \
1061 DEVMETH_OR_GIVEN (d, device_system_metrics, \
1062 (d, DM_##m), Qunbound)))) \
1063 plist = Fcons (Q##m, Fcons (one_metric, plist));
1065 FROB(color_default);
1067 FROB(color_balloon);
1068 FROB(color_3d_face);
1069 FROB(color_3d_light);
1070 FROB(color_3d_dark);
1072 FROB(color_menu_highlight);
1073 FROB(color_menu_button);
1074 FROB(color_menu_disabled);
1075 FROB(color_toolbar);
1076 FROB(color_scrollbar);
1077 FROB(color_desktop);
1078 FROB(color_workspace);
1083 FROB(size_scrollbar);
1086 FROB(size_toolbar_button);
1087 FROB(size_toolbar_border);
1089 FROB(size_icon_small);
1091 FROB(size_workspace);
1092 FROB(offset_workspace);
1093 FROB(size_device_mm);
1095 FROB(num_bit_planes);
1096 FROB(num_color_cells);
1097 FROB(mouse_buttons);
1108 Lisp_Object domain_device_type(Lisp_Object domain)
1110 /* This cannot GC */
1111 assert(WINDOWP(domain) || FRAMEP(domain)
1112 || DEVICEP(domain) || CONSOLEP(domain));
1114 if (WINDOWP(domain)) {
1115 if (!WINDOW_LIVE_P(XWINDOW(domain)))
1117 domain = WINDOW_FRAME(XWINDOW(domain));
1119 if (FRAMEP(domain)) {
1120 if (!FRAME_LIVE_P(XFRAME(domain)))
1122 domain = FRAME_DEVICE(XFRAME(domain));
1124 if (DEVICEP(domain)) {
1125 if (!DEVICE_LIVE_P(XDEVICE(domain)))
1127 domain = DEVICE_CONSOLE(XDEVICE(domain));
1129 return CONSOLE_TYPE(XCONSOLE(domain));
1133 * Determine whether window system bases window geometry on character
1135 * Return non-zero for pixel-based geometry, zero for character-based.
1137 int window_system_pixelated_geometry(Lisp_Object domain)
1139 /* This cannot GC */
1140 Lisp_Object winsy = domain_device_type(domain);
1141 struct console_methods *meth = decode_console_type(winsy, ERROR_ME_NOT);
1143 return CONMETH_IMPL_FLAG(meth, XDEVIMPF_PIXEL_GEOMETRY);
1146 DEFUN("domain-device-type", Fdomain_device_type, 0, 1, 0, /*
1147 Return the device type symbol for a DOMAIN, e.g. 'x or 'tty.
1148 DOMAIN can be either a window, frame, device or console.
1152 if (!WINDOWP(domain) && !FRAMEP(domain)
1153 && !DEVICEP(domain) && !CONSOLEP(domain))
1155 ("Domain must be either a window, frame, device or console",
1158 return domain_device_type(domain);
1161 void handle_asynch_device_change(void)
1164 int old_asynch_device_change_pending = asynch_device_change_pending;
1165 for (i = 0; i < Dynarr_length(the_console_type_entry_dynarr); i++) {
1166 if (Dynarr_at(the_console_type_entry_dynarr, i).meths->
1167 asynch_device_change_method)
1168 (Dynarr_at(the_console_type_entry_dynarr, i).meths->
1169 asynch_device_change_method) ();
1171 /* reset the flag to 0 unless another notification occurred while
1172 we were processing this one. Block SIGWINCH during this
1173 check to prevent a possible race condition. */
1175 EMACS_BLOCK_SIGNAL(SIGWINCH);
1177 if (old_asynch_device_change_pending == asynch_device_change_pending)
1178 asynch_device_change_pending = 0;
1180 EMACS_UNBLOCK_SIGNAL(SIGWINCH);
1185 call_critical_lisp_code(struct device *d, Lisp_Object function,
1188 int old_gc_currently_forbidden = gc_currently_forbidden;
1189 Lisp_Object old_inhibit_quit = Vinhibit_quit;
1191 /* There's no reason to bother doing specbinds here, because if
1192 initialize-*-faces signals an error, emacs is going to crash
1195 gc_currently_forbidden = 1;
1199 /* But it's useful to have an error handler; otherwise an infinite
1202 call1_with_handler(Qreally_early_error_handler, function,
1205 call0_with_handler(Qreally_early_error_handler, function);
1208 Vinhibit_quit = old_inhibit_quit;
1209 gc_currently_forbidden = old_gc_currently_forbidden;
1212 /************************************************************************/
1213 /* initialization */
1214 /************************************************************************/
1216 void syms_of_device(void)
1218 INIT_LRECORD_IMPLEMENTATION(device);
1220 DEFSUBR(Fvalid_device_class_p);
1221 DEFSUBR(Fdevice_class_list);
1223 DEFSUBR(Fdfw_device);
1224 DEFSUBR(Fselected_device);
1225 DEFSUBR(Fselect_device);
1226 DEFSUBR(Fset_device_selected_frame);
1228 DEFSUBR(Fdevice_live_p);
1229 DEFSUBR(Fdevice_name);
1230 DEFSUBR(Fdevice_connection);
1231 DEFSUBR(Fdevice_console);
1232 DEFSUBR(Ffind_device);
1233 DEFSUBR(Fget_device);
1234 DEFSUBR(Fmake_device);
1235 DEFSUBR(Fdelete_device);
1236 DEFSUBR(Fdevice_frame_list);
1237 DEFSUBR(Fdevice_class);
1238 DEFSUBR(Fset_device_class);
1239 DEFSUBR(Fdevice_system_metrics);
1240 DEFSUBR(Fdevice_system_metric);
1241 DEFSUBR(Fset_device_baud_rate);
1242 DEFSUBR(Fdevice_baud_rate);
1243 DEFSUBR(Fdomain_device_type);
1244 DEFSUBR(Fdevice_printer_p);
1246 defsymbol(&Qdevicep, "devicep");
1247 defsymbol(&Qdevice_live_p, "device-live-p");
1249 defsymbol(&Qcreate_device_hook, "create-device-hook");
1250 defsymbol(&Qdelete_device_hook, "delete-device-hook");
1252 /* Qcolor defined in general.c */
1253 defsymbol(&Qgrayscale, "grayscale");
1254 defsymbol(&Qmono, "mono");
1256 /* Device metrics symbols */
1257 defsymbol(&Qcolor_default, "color-default");
1258 defsymbol(&Qcolor_select, "color-select");
1259 defsymbol(&Qcolor_balloon, "color-balloon");
1260 defsymbol(&Qcolor_3d_face, "color-3d-face");
1261 defsymbol(&Qcolor_3d_light, "color-3d-light");
1262 defsymbol(&Qcolor_3d_dark, "color-3d-dark");
1263 defsymbol(&Qcolor_menu, "color-menu");
1264 defsymbol(&Qcolor_menu_highlight, "color-menu-highlight");
1265 defsymbol(&Qcolor_menu_button, "color-menu-button");
1266 defsymbol(&Qcolor_menu_disabled, "color-menu-disabled");
1267 defsymbol(&Qcolor_toolbar, "color-toolbar");
1268 defsymbol(&Qcolor_scrollbar, "color-scrollbar");
1269 defsymbol(&Qcolor_desktop, "color-desktop");
1270 defsymbol(&Qcolor_workspace, "color-workspace");
1271 defsymbol(&Qfont_default, "font-default");
1272 defsymbol(&Qfont_menubar, "font-menubar");
1273 defsymbol(&Qfont_dialog, "font-dialog");
1274 defsymbol(&Qsize_cursor, "size-cursor");
1275 defsymbol(&Qsize_scrollbar, "size-scrollbar");
1276 defsymbol(&Qsize_menu, "size-menu");
1277 defsymbol(&Qsize_toolbar, "size-toolbar");
1278 defsymbol(&Qsize_toolbar_button, "size-toolbar-button");
1279 defsymbol(&Qsize_toolbar_border, "size-toolbar-border");
1280 defsymbol(&Qsize_icon, "size-icon");
1281 defsymbol(&Qsize_icon_small, "size-icon-small");
1282 defsymbol(&Qsize_device, "size-device");
1283 defsymbol(&Qsize_workspace, "size-workspace");
1284 defsymbol(&Qoffset_workspace, "offset-workspace");
1285 defsymbol(&Qsize_device_mm, "size-device-mm");
1286 defsymbol(&Qnum_bit_planes, "num-bit-planes");
1287 defsymbol(&Qnum_color_cells, "num-color-cells");
1288 defsymbol(&Qdevice_dpi, "device-dpi");
1289 defsymbol(&Qmouse_buttons, "mouse-buttons");
1290 defsymbol(&Qswap_buttons, "swap-buttons");
1291 defsymbol(&Qshow_sounds, "show-sounds");
1292 defsymbol(&Qslow_device, "slow-device");
1293 defsymbol(&Qsecurity, "security");
1296 void reinit_vars_of_device(void)
1298 staticpro_nodump(&Vdefault_device);
1299 Vdefault_device = Qnil;
1300 asynch_device_change_pending = 0;
1303 void vars_of_device(void)
1305 reinit_vars_of_device();
1307 DEFVAR_LISP("create-device-hook", &Vcreate_device_hook /*
1308 Function or functions to call when a device is created.
1309 One argument, the newly-created device.
1310 This is called after the first frame has been created, but before
1311 calling the `create-frame-hook'.
1312 Note that in general the device will not be selected.
1314 Vcreate_device_hook = Qnil;
1316 DEFVAR_LISP("delete-device-hook", &Vdelete_device_hook /*
1317 Function or functions to call when a device is deleted.
1318 One argument, the to-be-deleted device.
1320 Vdelete_device_hook = Qnil;
1322 Vdevice_class_list = list3(Qcolor, Qgrayscale, Qmono);
1323 staticpro(&Vdevice_class_list);
1325 /* Death to devices.el !!! */
1326 Fprovide(intern("devices"));