1 /* NeXT/Open/GNUstep / MacOSX communication module.
3 Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2013 Free Software
6 This file is part of GNU Emacs.
8 GNU Emacs 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 GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 Originally by Carl Edman
23 Updated by Christian Limpach (chris@nice.ch)
24 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
29 /* This should be the first include, as it may set up #defines affecting
30 interpretation of even the system includes. */
36 #include <sys/types.h>
42 #include <c-strcase.h>
46 #include "blockinput.h"
47 #include "sysselect.h"
50 #include "character.h"
52 #include "composite.h"
55 #include "termhooks.h"
65 int term_trace_num = 0;
66 #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
67 __FILE__, __LINE__, ++term_trace_num)
72 extern NSString *NSMenuDidBeginTrackingNotification;
74 /* ==========================================================================
78 ========================================================================== */
80 /* Convert a symbol indexed with an NSxxx value to a value as defined
81 in keyboard.c (lispy_function_key). I hope this is a correct way
83 static unsigned convert_ns_to_X_keysym[] =
85 NSHomeFunctionKey, 0x50,
86 NSLeftArrowFunctionKey, 0x51,
87 NSUpArrowFunctionKey, 0x52,
88 NSRightArrowFunctionKey, 0x53,
89 NSDownArrowFunctionKey, 0x54,
90 NSPageUpFunctionKey, 0x55,
91 NSPageDownFunctionKey, 0x56,
92 NSEndFunctionKey, 0x57,
93 NSBeginFunctionKey, 0x58,
94 NSSelectFunctionKey, 0x60,
95 NSPrintFunctionKey, 0x61,
96 NSClearLineFunctionKey, 0x0B,
97 NSExecuteFunctionKey, 0x62,
98 NSInsertFunctionKey, 0x63,
99 NSUndoFunctionKey, 0x65,
100 NSRedoFunctionKey, 0x66,
101 NSMenuFunctionKey, 0x67,
102 NSFindFunctionKey, 0x68,
103 NSHelpFunctionKey, 0x6A,
104 NSBreakFunctionKey, 0x6B,
106 NSF1FunctionKey, 0xBE,
107 NSF2FunctionKey, 0xBF,
108 NSF3FunctionKey, 0xC0,
109 NSF4FunctionKey, 0xC1,
110 NSF5FunctionKey, 0xC2,
111 NSF6FunctionKey, 0xC3,
112 NSF7FunctionKey, 0xC4,
113 NSF8FunctionKey, 0xC5,
114 NSF9FunctionKey, 0xC6,
115 NSF10FunctionKey, 0xC7,
116 NSF11FunctionKey, 0xC8,
117 NSF12FunctionKey, 0xC9,
118 NSF13FunctionKey, 0xCA,
119 NSF14FunctionKey, 0xCB,
120 NSF15FunctionKey, 0xCC,
121 NSF16FunctionKey, 0xCD,
122 NSF17FunctionKey, 0xCE,
123 NSF18FunctionKey, 0xCF,
124 NSF19FunctionKey, 0xD0,
125 NSF20FunctionKey, 0xD1,
126 NSF21FunctionKey, 0xD2,
127 NSF22FunctionKey, 0xD3,
128 NSF23FunctionKey, 0xD4,
129 NSF24FunctionKey, 0xD5,
131 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
132 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
133 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
135 NSTabCharacter, 0x09,
136 0x19, 0x09, /* left tab->regular since pass shift */
137 NSCarriageReturnCharacter, 0x0D,
138 NSNewlineCharacter, 0x0D,
139 NSEnterCharacter, 0x8D,
141 0x41|NSNumericPadKeyMask, 0xAE, /* KP_Decimal */
142 0x43|NSNumericPadKeyMask, 0xAA, /* KP_Multiply */
143 0x45|NSNumericPadKeyMask, 0xAB, /* KP_Add */
144 0x4B|NSNumericPadKeyMask, 0xAF, /* KP_Divide */
145 0x4E|NSNumericPadKeyMask, 0xAD, /* KP_Subtract */
146 0x51|NSNumericPadKeyMask, 0xBD, /* KP_Equal */
147 0x52|NSNumericPadKeyMask, 0xB0, /* KP_0 */
148 0x53|NSNumericPadKeyMask, 0xB1, /* KP_1 */
149 0x54|NSNumericPadKeyMask, 0xB2, /* KP_2 */
150 0x55|NSNumericPadKeyMask, 0xB3, /* KP_3 */
151 0x56|NSNumericPadKeyMask, 0xB4, /* KP_4 */
152 0x57|NSNumericPadKeyMask, 0xB5, /* KP_5 */
153 0x58|NSNumericPadKeyMask, 0xB6, /* KP_6 */
154 0x59|NSNumericPadKeyMask, 0xB7, /* KP_7 */
155 0x5B|NSNumericPadKeyMask, 0xB8, /* KP_8 */
156 0x5C|NSNumericPadKeyMask, 0xB9, /* KP_9 */
158 0x1B, 0x1B /* escape */
161 static Lisp_Object Qmodifier_value;
162 Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
163 extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft;
165 static Lisp_Object QUTF8_STRING;
167 /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
168 the maximum font size to NOT antialias. On GNUstep there is currently
169 no way to control this behavior. */
170 float ns_antialias_threshold;
172 /* Used to pick up AppleHighlightColor on OS X */
173 NSString *ns_selection_color;
175 NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
176 NSString *ns_app_name = @"Emacs"; /* default changed later */
178 /* Display variables */
179 struct ns_display_info *x_display_list; /* Chain of existing displays */
180 Lisp_Object ns_display_name_list;
181 long context_menu_value = 0;
184 NSPoint last_mouse_motion_position;
185 static NSRect last_mouse_glyph;
186 static Time last_mouse_movement_time = 0;
187 static Lisp_Object last_mouse_motion_frame;
188 static EmacsScroller *last_mouse_scroll_bar = nil;
189 static struct frame *ns_updating_frame;
190 static NSView *focus_view = NULL;
191 static int ns_window_num = 0;
192 #ifdef NS_IMPL_GNUSTEP
195 static BOOL gsaved = NO;
196 static BOOL ns_fake_keydown = NO;
197 int ns_tmp_flags; /* FIXME */
198 struct nsfont_info *ns_tmp_font; /* FIXME */
199 static BOOL ns_menu_bar_is_hidden = NO;
200 /*static int debug_lock = 0; */
203 static BOOL send_appdefined = YES;
204 #define NO_APPDEFINED_DATA (-8)
205 static int last_appdefined_event_data = NO_APPDEFINED_DATA;
206 static NSTimer *timed_entry = 0;
207 static NSTimer *scroll_repeat_entry = nil;
208 static fd_set select_readfds, select_writefds;
209 enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 };
210 static int select_nfds = 0, select_valid = 0;
211 static EMACS_TIME select_timeout = { 0, 0 };
212 static int selfds[2] = { -1, -1 };
213 static pthread_mutex_t select_mutex;
214 static int apploopnr = 0;
215 static NSAutoreleasePool *outerpool;
216 static struct input_event *emacs_event = NULL;
217 static struct input_event *q_event_ptr = NULL;
218 static int n_emacs_events_pending = 0;
219 static NSMutableArray *ns_pending_files, *ns_pending_service_names,
220 *ns_pending_service_args;
221 static BOOL ns_do_open_file = NO;
222 static BOOL ns_last_use_native_fullscreen;
225 struct input_event *q;
232 * State for pending menu activation:
233 * MENU_NONE Normal state
234 * MENU_PENDING A menu has been clicked on, but has been canceled so we can
235 * run lisp to update the menu.
236 * MENU_OPENING Menu is up to date, and the click event is redone so the menu
240 #define MENU_PENDING 1
241 #define MENU_OPENING 2
242 static int menu_will_open_state = MENU_NONE;
244 /* Saved position for menu click. */
245 static CGPoint menu_mouse_point;
247 /* Title for the menu to open. */
248 static char *menu_pending_title = 0;
250 /* Convert modifiers in a NeXTstep event to emacs style modifiers. */
251 #define NS_FUNCTION_KEY_MASK 0x800000
252 #define NSLeftControlKeyMask (0x000001 | NSControlKeyMask)
253 #define NSRightControlKeyMask (0x002000 | NSControlKeyMask)
254 #define NSLeftCommandKeyMask (0x000008 | NSCommandKeyMask)
255 #define NSRightCommandKeyMask (0x000010 | NSCommandKeyMask)
256 #define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
257 #define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
258 #define EV_MODIFIERS(e) \
259 ((([e modifierFlags] & NSHelpKeyMask) ? \
260 hyper_modifier : 0) \
261 | (!EQ (ns_right_alternate_modifier, Qleft) && \
262 (([e modifierFlags] & NSRightAlternateKeyMask) \
263 == NSRightAlternateKeyMask) ? \
264 parse_solitary_modifier (ns_right_alternate_modifier) : 0) \
265 | (([e modifierFlags] & NSAlternateKeyMask) ? \
266 parse_solitary_modifier (ns_alternate_modifier) : 0) \
267 | (([e modifierFlags] & NSShiftKeyMask) ? \
268 shift_modifier : 0) \
269 | (!EQ (ns_right_control_modifier, Qleft) && \
270 (([e modifierFlags] & NSRightControlKeyMask) \
271 == NSRightControlKeyMask) ? \
272 parse_solitary_modifier (ns_right_control_modifier) : 0) \
273 | (([e modifierFlags] & NSControlKeyMask) ? \
274 parse_solitary_modifier (ns_control_modifier) : 0) \
275 | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \
276 parse_solitary_modifier (ns_function_modifier) : 0) \
277 | (!EQ (ns_right_command_modifier, Qleft) && \
278 (([e modifierFlags] & NSRightCommandKeyMask) \
279 == NSRightCommandKeyMask) ? \
280 parse_solitary_modifier (ns_right_command_modifier) : 0) \
281 | (([e modifierFlags] & NSCommandKeyMask) ? \
282 parse_solitary_modifier (ns_command_modifier):0))
284 #define EV_UDMODIFIERS(e) \
285 ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
286 | (([e type] == NSRightMouseDown) ? down_modifier : 0) \
287 | (([e type] == NSOtherMouseDown) ? down_modifier : 0) \
288 | (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
289 | (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
290 | (([e type] == NSOtherMouseDragged) ? down_modifier : 0) \
291 | (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
292 | (([e type] == NSRightMouseUp) ? up_modifier : 0) \
293 | (([e type] == NSOtherMouseUp) ? up_modifier : 0))
295 #define EV_BUTTON(e) \
296 ((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
297 (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : \
298 [e buttonNumber] - 1)
300 /* Convert the time field to a timestamp in milliseconds. */
301 #define EV_TIMESTAMP(e) ([e timestamp] * 1000)
303 /* This is a piece of code which is common to all the event handling
304 methods. Maybe it should even be a function. */
305 #define EV_TRAILER(e) \
307 XSETFRAME (emacs_event->frame_or_window, emacsframe); \
308 if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
311 n_emacs_events_pending++; \
312 kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
315 hold_event (emacs_event); \
316 EVENT_INIT (*emacs_event); \
317 ns_send_appdefined (-1); \
320 void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
322 /* TODO: get rid of need for these forward declarations */
323 static void ns_condemn_scroll_bars (struct frame *f);
324 static void ns_judge_scroll_bars (struct frame *f);
325 void x_set_frame_alpha (struct frame *f);
328 /* ==========================================================================
332 ========================================================================== */
335 hold_event (struct input_event *event)
337 if (hold_event_q.nr == hold_event_q.cap)
339 if (hold_event_q.cap == 0) hold_event_q.cap = 10;
340 else hold_event_q.cap *= 2;
341 hold_event_q.q = (struct input_event *)
342 xrealloc (hold_event_q.q, hold_event_q.cap * sizeof (*hold_event_q.q));
345 hold_event_q.q[hold_event_q.nr++] = *event;
346 /* Make sure ns_read_socket is called, i.e. we have input. */
348 send_appdefined = YES;
352 append2 (Lisp_Object list, Lisp_Object item)
353 /* --------------------------------------------------------------------------
354 Utility to append to a list
355 -------------------------------------------------------------------------- */
357 Lisp_Object array[2];
359 array[1] = Fcons (item, Qnil);
360 return Fnconc (2, &array[0]);
365 ns_etc_directory (void)
366 /* If running as a self-contained app bundle, return as a string the
367 filename of the etc directory, if present; else nil. */
369 NSBundle *bundle = [NSBundle mainBundle];
370 NSString *resourceDir = [bundle resourcePath];
371 NSString *resourcePath;
372 NSFileManager *fileManager = [NSFileManager defaultManager];
375 resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"];
376 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
378 if (isDir) return [resourcePath UTF8String];
386 /* If running as a self-contained app bundle, return as a path string
387 the filenames of the libexec and bin directories, ie libexec:bin.
388 Otherwise, return nil.
389 Normally, Emacs does not add its own bin/ directory to the PATH.
390 However, a self-contained NS build has a different layout, with
391 bin/ and libexec/ subdirectories in the directory that contains
393 We put libexec first, because init_callproc_1 uses the first
394 element to initialize exec-directory. An alternative would be
395 for init_callproc to check for invocation-directory/libexec.
398 NSBundle *bundle = [NSBundle mainBundle];
399 NSString *resourceDir = [bundle resourcePath];
400 NSString *binDir = [bundle bundlePath];
401 NSString *resourcePath, *resourcePaths;
403 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
404 NSFileManager *fileManager = [NSFileManager defaultManager];
406 NSEnumerator *pathEnum;
409 range = [resourceDir rangeOfString: @"Contents"];
410 if (range.location != NSNotFound)
412 binDir = [binDir stringByAppendingPathComponent: @"Contents"];
414 binDir = [binDir stringByAppendingPathComponent: @"MacOS"];
418 paths = [binDir stringsByAppendingPaths:
419 [NSArray arrayWithObjects: @"libexec", @"bin", nil]];
420 pathEnum = [paths objectEnumerator];
423 while ((resourcePath = [pathEnum nextObject]))
425 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
428 if ([resourcePaths length] > 0)
430 = [resourcePaths stringByAppendingString: pathSeparator];
432 = [resourcePaths stringByAppendingString: resourcePath];
435 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
443 /* If running as a self-contained app bundle, return as a path string
444 the filenames of the site-lisp, lisp and leim directories.
445 Ie, site-lisp:lisp:leim. Otherwise, return nil. */
447 NSBundle *bundle = [NSBundle mainBundle];
448 NSString *resourceDir = [bundle resourcePath];
449 NSString *resourcePath, *resourcePaths;
450 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
451 NSFileManager *fileManager = [NSFileManager defaultManager];
453 NSArray *paths = [resourceDir stringsByAppendingPaths:
454 [NSArray arrayWithObjects:
455 @"site-lisp", @"lisp", @"leim", nil]];
456 NSEnumerator *pathEnum = [paths objectEnumerator];
459 /* Hack to skip site-lisp. */
460 if (no_site_lisp) resourcePath = [pathEnum nextObject];
462 while ((resourcePath = [pathEnum nextObject]))
464 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
467 if ([resourcePaths length] > 0)
469 = [resourcePaths stringByAppendingString: pathSeparator];
471 = [resourcePaths stringByAppendingString: resourcePath];
474 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
480 ns_timeout (int usecs)
481 /* --------------------------------------------------------------------------
482 Blocking timer utility used by ns_ring_bell
483 -------------------------------------------------------------------------- */
485 EMACS_TIME wakeup = add_emacs_time (current_emacs_time (),
486 make_emacs_time (0, usecs * 1000));
488 /* Keep waiting until past the time wakeup. */
491 EMACS_TIME timeout, now = current_emacs_time ();
492 if (EMACS_TIME_LE (wakeup, now))
494 timeout = sub_emacs_time (wakeup, now);
496 /* Try to wait that long--but we might wake up sooner. */
497 pselect (0, NULL, NULL, NULL, &timeout, NULL);
503 ns_release_object (void *obj)
504 /* --------------------------------------------------------------------------
505 Release an object (callable from C)
506 -------------------------------------------------------------------------- */
513 ns_retain_object (void *obj)
514 /* --------------------------------------------------------------------------
515 Retain an object (callable from C)
516 -------------------------------------------------------------------------- */
523 ns_alloc_autorelease_pool (void)
524 /* --------------------------------------------------------------------------
525 Allocate a pool for temporary objects (callable from C)
526 -------------------------------------------------------------------------- */
528 return [[NSAutoreleasePool alloc] init];
533 ns_release_autorelease_pool (void *pool)
534 /* --------------------------------------------------------------------------
535 Free a pool and temporary objects it refers to (callable from C)
536 -------------------------------------------------------------------------- */
538 ns_release_object (pool);
543 /* ==========================================================================
545 Focus (clipping) and screen update
547 ========================================================================== */
550 // Window constraining
551 // -------------------
553 // To ensure that the windows are not placed under the menu bar, they
554 // are typically moved by the call-back constrainFrameRect. However,
555 // by overriding it, it's possible to inhibit this, leaving the window
556 // in it's original position.
558 // It's possible to hide the menu bar. However, technically, it's only
559 // possible to hide it when the application is active. To ensure that
560 // this work properly, the menu bar and window constraining are
561 // deferred until the application becomes active.
563 // Even though it's not possible to manually move a window above the
564 // top of the screen, it is allowed if it's done programmatically,
565 // when the menu is hidden. This allows the editable area to cover the
566 // full screen height.
571 // Use the following extra files:
574 // ;; Hide menu and place frame slightly above the top of the screen.
575 // (setq ns-auto-hide-menu-bar t)
576 // (set-frame-position (selected-frame) 0 -20)
580 // emacs -Q -l init.el
582 // Result: No menu bar, and the title bar should be above the screen.
588 // Result: Menu bar visible, frame placed immediately below the menu.
592 ns_constrain_all_frames (void)
594 Lisp_Object tail, frame;
596 FOR_EACH_FRAME (tail, frame)
598 struct frame *f = XFRAME (frame);
601 NSView *view = FRAME_NS_VIEW (f);
602 /* This no-op will trigger the default window placing
603 * constraint system. */
604 f->output_data.ns->dont_constrain = 0;
605 [[view window] setFrameOrigin:[[view window] frame].origin];
611 /* True, if the menu bar should be hidden. */
614 ns_menu_bar_should_be_hidden (void)
616 return !NILP (ns_auto_hide_menu_bar)
617 && [NSApp respondsToSelector:@selector(setPresentationOptions:)];
621 /* Show or hide the menu bar, based on user setting. */
624 ns_update_auto_hide_menu_bar (void)
627 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
630 NSTRACE (ns_update_auto_hide_menu_bar);
634 && [NSApp respondsToSelector:@selector(setPresentationOptions:)])
636 // Note, "setPresentationOptions" triggers an error unless the
637 // application is active.
638 BOOL menu_bar_should_be_hidden = ns_menu_bar_should_be_hidden ();
640 if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden)
642 NSApplicationPresentationOptions options
643 = NSApplicationPresentationAutoHideDock;
645 if (menu_bar_should_be_hidden)
646 options |= NSApplicationPresentationAutoHideMenuBar;
648 [NSApp setPresentationOptions: options];
650 ns_menu_bar_is_hidden = menu_bar_should_be_hidden;
652 if (!ns_menu_bar_is_hidden)
654 ns_constrain_all_frames ();
666 ns_update_begin (struct frame *f)
667 /* --------------------------------------------------------------------------
668 Prepare for a grouped sequence of drawing calls
669 external (RIF) call; whole frame, called before update_window_begin
670 -------------------------------------------------------------------------- */
672 NSView *view = FRAME_NS_VIEW (f);
673 NSRect r = [view frame];
675 NSTRACE (ns_update_begin);
677 ns_update_auto_hide_menu_bar ();
679 ns_updating_frame = f;
682 /* drawRect may have been called for say the minibuffer, and then clip path
683 is for the minibuffer. But the display engine may draw more because
684 we have set the frame as garbaged. So reset clip path to the whole
686 bp = [[NSBezierPath bezierPathWithRect: r] retain];
690 #ifdef NS_IMPL_GNUSTEP
691 uRect = NSMakeRect (0, 0, 0, 0);
697 ns_update_window_begin (struct window *w)
698 /* --------------------------------------------------------------------------
699 Prepare for a grouped sequence of drawing calls
700 external (RIF) call; for one window, called after update_begin
701 -------------------------------------------------------------------------- */
703 struct frame *f = XFRAME (WINDOW_FRAME (w));
704 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
705 NSTRACE (ns_update_window_begin);
707 set_output_cursor (&w->cursor);
711 if (f == hlinfo->mouse_face_mouse_frame)
713 /* Don't do highlighting for mouse motion during the update. */
714 hlinfo->mouse_face_defer = 1;
716 /* If the frame needs to be redrawn,
717 simply forget about any prior mouse highlighting. */
718 if (FRAME_GARBAGED_P (f))
719 hlinfo->mouse_face_window = Qnil;
721 /* (further code for mouse faces ifdef'd out in other terms elided) */
729 ns_update_window_end (struct window *w, int cursor_on_p,
730 int mouse_face_overwritten_p)
731 /* --------------------------------------------------------------------------
732 Finished a grouped sequence of drawing calls
733 external (RIF) call; for one window called before update_end
734 -------------------------------------------------------------------------- */
736 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
738 /* note: this fn is nearly identical in all terms */
739 if (!w->pseudo_window_p)
744 display_and_set_cursor (w, 1,
745 output_cursor.hpos, output_cursor.vpos,
746 output_cursor.x, output_cursor.y);
748 if (draw_window_fringes (w, 1))
749 x_draw_vertical_border (w);
754 /* If a row with mouse-face was overwritten, arrange for
755 frame_up_to_date to redisplay the mouse highlight. */
756 if (mouse_face_overwritten_p)
758 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
759 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
760 hlinfo->mouse_face_window = Qnil;
763 updated_window = NULL;
764 NSTRACE (update_window_end);
769 ns_update_end (struct frame *f)
770 /* --------------------------------------------------------------------------
771 Finished a grouped sequence of drawing calls
772 external (RIF) call; for whole frame, called after update_window_end
773 -------------------------------------------------------------------------- */
775 NSView *view = FRAME_NS_VIEW (f);
777 /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
778 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
782 #ifdef NS_IMPL_GNUSTEP
783 /* trigger flush only in the rectangle we tracked as being drawn */
784 [view unlockFocusNeedsFlush: NO];
785 /*fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", uRect.origin.x, uRect.origin.y, uRect.size.width, uRect.size.height); */
786 [view lockFocusInRect: uRect];
790 [[view window] flushWindow];
793 ns_updating_frame = NULL;
794 NSTRACE (ns_update_end);
799 ns_flush (struct frame *f)
800 /* --------------------------------------------------------------------------
802 NS impl is no-op since currently we flush in ns_update_end and elsewhere
803 -------------------------------------------------------------------------- */
810 ns_focus (struct frame *f, NSRect *r, int n)
811 /* --------------------------------------------------------------------------
812 Internal: Focus on given frame. During small local updates this is used to
813 draw, however during large updates, ns_update_begin and ns_update_end are
814 called to wrap the whole thing, in which case these calls are stubbed out.
815 Except, on GNUstep, we accumulate the rectangle being drawn into, because
816 the back end won't do this automatically, and will just end up flushing
818 -------------------------------------------------------------------------- */
820 // NSTRACE (ns_focus);
821 #ifdef NS_IMPL_GNUSTEP
824 u = NSUnionRect (r[0], r[1]);
829 fprintf (stderr, "focus: %d", c++);
830 if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height);
831 fprintf (stderr, "\n"); */
833 if (f != ns_updating_frame)
835 NSView *view = FRAME_NS_VIEW (f);
836 if (view != focus_view)
838 if (focus_view != NULL)
840 [focus_view unlockFocus];
841 [[focus_view window] flushWindow];
846 #ifdef NS_IMPL_GNUSTEP
847 r ? [view lockFocusInRect: u] : [view lockFocus];
852 /*if (view) debug_lock++; */
854 #ifdef NS_IMPL_GNUSTEP
857 /* more than one rect being drawn into */
860 [view unlockFocus]; /* add prev rect to redraw list */
861 [view lockFocusInRect: u]; /* focus for draw in new rect */
866 #ifdef NS_IMPL_GNUSTEP
869 /* in batch mode, but in GNUstep must still track rectangles explicitly */
870 uRect = (r ? NSUnionRect (uRect, u) : [FRAME_NS_VIEW (f) visibleRect]);
877 [[NSGraphicsContext currentContext] saveGraphicsState];
879 NSRectClipList (r, 2);
888 ns_unfocus (struct frame *f)
889 /* --------------------------------------------------------------------------
890 Internal: Remove focus on given frame
891 -------------------------------------------------------------------------- */
893 // NSTRACE (ns_unfocus);
897 [[NSGraphicsContext currentContext] restoreGraphicsState];
901 if (f != ns_updating_frame)
903 if (focus_view != NULL)
905 [focus_view unlockFocus];
906 [[focus_view window] flushWindow];
915 ns_clip_to_row (struct window *w, struct glyph_row *row, int area, BOOL gc)
916 /* --------------------------------------------------------------------------
917 Internal (but parallels other terms): Focus drawing on given row
918 -------------------------------------------------------------------------- */
920 struct frame *f = XFRAME (WINDOW_FRAME (w));
922 int window_x, window_y, window_width;
924 window_box (w, area, &window_x, &window_y, &window_width, 0);
926 clip_rect.origin.x = window_x;
927 clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
928 clip_rect.origin.y = max (clip_rect.origin.y, window_y);
929 clip_rect.size.width = window_width;
930 clip_rect.size.height = row->visible_height;
932 ns_focus (f, &clip_rect, 1);
937 ns_ring_bell (struct frame *f)
938 /* --------------------------------------------------------------------------
940 -------------------------------------------------------------------------- */
942 NSTRACE (ns_ring_bell);
945 NSAutoreleasePool *pool;
946 struct frame *frame = SELECTED_FRAME ();
950 pool = [[NSAutoreleasePool alloc] init];
952 view = FRAME_NS_VIEW (frame);
956 NSPoint dim = NSMakePoint (128, 128);
959 r.origin.x += (r.size.width - dim.x) / 2;
960 r.origin.y += (r.size.height - dim.y) / 2;
961 r.size.width = dim.x;
962 r.size.height = dim.y;
963 surr = NSInsetRect (r, -2, -2);
964 ns_focus (frame, &surr, 1);
965 [[view window] cacheImageInRect: [view convertRect: surr toView:nil]];
966 [ns_lookup_indexed_color (NS_FACE_FOREGROUND
967 (FRAME_DEFAULT_FACE (frame)), frame) set];
969 [[view window] flushWindow];
971 [[view window] restoreCachedImage];
972 [[view window] flushWindow];
986 ns_reset_terminal_modes (struct terminal *terminal)
987 /* Externally called as hook */
989 NSTRACE (ns_reset_terminal_modes);
994 ns_set_terminal_modes (struct terminal *terminal)
995 /* Externally called as hook */
997 NSTRACE (ns_set_terminal_modes);
1002 /* ==========================================================================
1004 Frame / window manager related functions
1006 ========================================================================== */
1010 ns_raise_frame (struct frame *f)
1011 /* --------------------------------------------------------------------------
1012 Bring window to foreground and make it active
1013 -------------------------------------------------------------------------- */
1016 check_window_system (f);
1017 view = FRAME_NS_VIEW (f);
1019 if (FRAME_VISIBLE_P (f))
1020 [[view window] makeKeyAndOrderFront: NSApp];
1026 ns_lower_frame (struct frame *f)
1027 /* --------------------------------------------------------------------------
1029 -------------------------------------------------------------------------- */
1032 check_window_system (f);
1033 view = FRAME_NS_VIEW (f);
1035 [[view window] orderBack: NSApp];
1041 ns_frame_raise_lower (struct frame *f, int raise)
1042 /* --------------------------------------------------------------------------
1044 -------------------------------------------------------------------------- */
1046 NSTRACE (ns_frame_raise_lower);
1056 ns_frame_rehighlight (struct frame *frame)
1057 /* --------------------------------------------------------------------------
1058 External (hook): called on things like window switching within frame
1059 -------------------------------------------------------------------------- */
1061 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
1062 struct frame *old_highlight = dpyinfo->x_highlight_frame;
1064 NSTRACE (ns_frame_rehighlight);
1065 if (dpyinfo->x_focus_frame)
1067 dpyinfo->x_highlight_frame
1068 = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1069 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1070 : dpyinfo->x_focus_frame);
1071 if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame))
1073 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
1074 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
1078 dpyinfo->x_highlight_frame = 0;
1080 if (dpyinfo->x_highlight_frame &&
1081 dpyinfo->x_highlight_frame != old_highlight)
1085 x_update_cursor (old_highlight, 1);
1086 x_set_frame_alpha (old_highlight);
1088 if (dpyinfo->x_highlight_frame)
1090 x_update_cursor (dpyinfo->x_highlight_frame, 1);
1091 x_set_frame_alpha (dpyinfo->x_highlight_frame);
1098 x_make_frame_visible (struct frame *f)
1099 /* --------------------------------------------------------------------------
1100 External: Show the window (X11 semantics)
1101 -------------------------------------------------------------------------- */
1103 NSTRACE (x_make_frame_visible);
1104 /* XXX: at some points in past this was not needed, as the only place that
1105 called this (frame.c:Fraise_frame ()) also called raise_lower;
1106 if this ends up the case again, comment this out again. */
1107 if (!FRAME_VISIBLE_P (f))
1109 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1111 SET_FRAME_VISIBLE (f, 1);
1114 /* Making a new frame from a fullscreen frame will make the new frame
1115 fullscreen also. So skip handleFS as this will print an error. */
1116 if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH
1117 && [view isFullscreen])
1120 if (f->want_fullscreen != FULLSCREEN_NONE)
1131 x_make_frame_invisible (struct frame *f)
1132 /* --------------------------------------------------------------------------
1133 External: Hide the window (X11 semantics)
1134 -------------------------------------------------------------------------- */
1137 NSTRACE (x_make_frame_invisible);
1138 check_window_system (f);
1139 view = FRAME_NS_VIEW (f);
1140 [[view window] orderOut: NSApp];
1141 SET_FRAME_VISIBLE (f, 0);
1142 SET_FRAME_ICONIFIED (f, 0);
1147 x_iconify_frame (struct frame *f)
1148 /* --------------------------------------------------------------------------
1149 External: Iconify window
1150 -------------------------------------------------------------------------- */
1153 struct ns_display_info *dpyinfo;
1155 NSTRACE (x_iconify_frame);
1156 check_window_system (f);
1157 view = FRAME_NS_VIEW (f);
1158 dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1160 if (dpyinfo->x_highlight_frame == f)
1161 dpyinfo->x_highlight_frame = 0;
1163 if ([[view window] windowNumber] <= 0)
1165 /* the window is still deferred. Make it very small, bring it
1166 on screen and order it out. */
1167 NSRect s = { { 100, 100}, {0, 0} };
1169 t = [[view window] frame];
1170 [[view window] setFrame: s display: NO];
1171 [[view window] orderBack: NSApp];
1172 [[view window] orderOut: NSApp];
1173 [[view window] setFrame: t display: NO];
1175 [[view window] miniaturize: NSApp];
1178 /* Free X resources of frame F. */
1181 x_free_frame_resources (struct frame *f)
1184 struct ns_display_info *dpyinfo;
1185 Mouse_HLInfo *hlinfo;
1187 NSTRACE (x_free_frame_resources);
1188 check_window_system (f);
1189 view = FRAME_NS_VIEW (f);
1190 dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1191 hlinfo = MOUSE_HL_INFO (f);
1193 [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
1197 free_frame_menubar (f);
1199 if (FRAME_FACE_CACHE (f))
1200 free_frame_faces (f);
1202 if (f == dpyinfo->x_focus_frame)
1203 dpyinfo->x_focus_frame = 0;
1204 if (f == dpyinfo->x_highlight_frame)
1205 dpyinfo->x_highlight_frame = 0;
1206 if (f == hlinfo->mouse_face_mouse_frame)
1208 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
1209 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
1210 hlinfo->mouse_face_window = Qnil;
1211 hlinfo->mouse_face_mouse_frame = 0;
1214 if (f->output_data.ns->miniimage != nil)
1215 [f->output_data.ns->miniimage release];
1217 [[view window] close];
1220 xfree (f->output_data.ns);
1226 x_destroy_window (struct frame *f)
1227 /* --------------------------------------------------------------------------
1228 External: Delete the window
1229 -------------------------------------------------------------------------- */
1231 NSTRACE (x_destroy_window);
1232 check_window_system (f);
1233 x_free_frame_resources (f);
1239 x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1240 /* --------------------------------------------------------------------------
1241 External: Position the window
1242 -------------------------------------------------------------------------- */
1244 NSView *view = FRAME_NS_VIEW (f);
1245 NSArray *screens = [NSScreen screens];
1246 NSScreen *fscreen = [screens objectAtIndex: 0];
1247 NSScreen *screen = [[view window] screen];
1249 NSTRACE (x_set_offset);
1256 if (view != nil && screen && fscreen)
1258 f->left_pos = f->size_hint_flags & XNegative
1259 ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
1261 /* We use visibleFrame here to take menu bar into account.
1262 Ideally we should also adjust left/top with visibleFrame.origin. */
1264 f->top_pos = f->size_hint_flags & YNegative
1265 ? ([screen visibleFrame].size.height + f->top_pos
1266 - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
1267 - FRAME_TOOLBAR_HEIGHT (f))
1269 #ifdef NS_IMPL_GNUSTEP
1270 if (f->left_pos < 100)
1271 f->left_pos = 100; /* don't overlap menu */
1273 /* Constrain the setFrameTopLeftPoint so we don't move behind the
1275 f->output_data.ns->dont_constrain = 0;
1276 [[view window] setFrameTopLeftPoint:
1277 NSMakePoint (SCREENMAXBOUND (f->left_pos),
1278 SCREENMAXBOUND ([fscreen frame].size.height
1279 - NS_TOP_POS (f)))];
1280 f->size_hint_flags &= ~(XNegative|YNegative);
1288 x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
1289 /* --------------------------------------------------------------------------
1290 Adjust window pixel size based on given character grid size
1291 Impl is a bit more complex than other terms, need to do some
1293 -------------------------------------------------------------------------- */
1295 EmacsView *view = FRAME_NS_VIEW (f);
1296 NSWindow *window = [view window];
1297 NSRect wr = [window frame];
1298 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1299 int pixelwidth, pixelheight;
1301 NSTRACE (x_set_window_size);
1306 /*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
1310 check_frame_size (f, &rows, &cols);
1312 f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
1313 compute_fringe_widths (f, 0);
1315 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
1316 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1318 /* If we have a toolbar, take its height into account. */
1319 if (tb && ! [view isFullscreen])
1320 /* NOTE: previously this would generate wrong result if toolbar not
1321 yet displayed and fixing toolbar_height=32 helped, but
1322 now (200903) seems no longer needed */
1323 FRAME_TOOLBAR_HEIGHT (f) =
1324 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1325 - FRAME_NS_TITLEBAR_HEIGHT (f);
1327 FRAME_TOOLBAR_HEIGHT (f) = 0;
1329 wr.size.width = pixelwidth + f->border_width;
1330 wr.size.height = pixelheight;
1331 if (! [view isFullscreen])
1332 wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f)
1333 + FRAME_TOOLBAR_HEIGHT (f);
1335 /* Do not try to constrain to this screen. We may have multiple
1336 screens, and want Emacs to span those. Constraining to screen
1337 prevents that, and that is not nice to the user. */
1338 if (f->output_data.ns->zooming)
1339 f->output_data.ns->zooming = 0;
1341 wr.origin.y += FRAME_PIXEL_HEIGHT (f) - pixelheight;
1343 [view setRows: rows andColumns: cols];
1344 [window setFrame: wr display: YES];
1346 /*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */
1348 /* This is a trick to compensate for Emacs' managing the scrollbar area
1349 as a fixed number of standard character columns. Instead of leaving
1350 blank space for the extra, we chopped it off above. Now for
1351 left-hand scrollbars, we shift all rendering to the left by the
1352 difference between the real width and Emacs' imagined one. For
1353 right-hand bars, don't worry about it since the extra is never used.
1354 (Obviously doesn't work for vertically split windows tho..) */
1356 NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
1357 ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
1358 - NS_SCROLL_BAR_WIDTH (f), 0)
1359 : NSMakePoint (0, 0);
1360 [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
1361 [view setBoundsOrigin: origin];
1364 change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
1365 FRAME_PIXEL_WIDTH (f) = pixelwidth;
1366 FRAME_PIXEL_HEIGHT (f) = pixelheight;
1367 /* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
1369 mark_window_cursors_off (XWINDOW (f->root_window));
1370 cancel_mouse_face (f);
1377 ns_fullscreen_hook (FRAME_PTR f)
1379 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1381 if (!FRAME_VISIBLE_P (f))
1384 if (! [view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH)
1386 /* Old style fs don't initiate correctly if created from
1387 init/default-frame alist, so use a timer (not nice...).
1389 [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view
1390 selector: @selector (handleFS)
1391 userInfo: nil repeats: NO];
1400 /* ==========================================================================
1404 ========================================================================== */
1408 ns_lookup_indexed_color (unsigned long idx, struct frame *f)
1410 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1411 if (idx < 1 || idx >= color_table->avail)
1413 return color_table->colors[idx];
1418 ns_index_color (NSColor *color, struct frame *f)
1420 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1424 if (!color_table->colors)
1426 color_table->size = NS_COLOR_CAPACITY;
1427 color_table->avail = 1; /* skip idx=0 as marker */
1428 color_table->colors = xmalloc (color_table->size * sizeof (NSColor *));
1429 color_table->colors[0] = nil;
1430 color_table->empty_indices = [[NSMutableSet alloc] init];
1433 /* do we already have this color ? */
1434 for (i = 1; i < color_table->avail; i++)
1435 if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
1438 if ([color_table->empty_indices count] > 0)
1440 NSNumber *index = [color_table->empty_indices anyObject];
1441 [color_table->empty_indices removeObject: index];
1442 idx = [index unsignedLongValue];
1446 if (color_table->avail == color_table->size)
1447 color_table->colors =
1448 xpalloc (color_table->colors, &color_table->size, 1,
1449 min (ULONG_MAX, PTRDIFF_MAX), sizeof *color_table->colors);
1450 idx = color_table->avail++;
1453 color_table->colors[idx] = color;
1455 /*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1461 ns_free_indexed_color (unsigned long idx, struct frame *f)
1463 struct ns_color_table *color_table;
1470 color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1472 if (idx <= 0 || idx >= color_table->size) {
1473 message1 ("ns_free_indexed_color: Color index out of range.\n");
1477 index = [NSNumber numberWithUnsignedInt: idx];
1478 if ([color_table->empty_indices containsObject: index]) {
1479 message1 ("ns_free_indexed_color: attempt to free already freed color.\n");
1483 color = color_table->colors[idx];
1485 color_table->colors[idx] = nil;
1486 [color_table->empty_indices addObject: index];
1487 /*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1492 ns_get_color (const char *name, NSColor **col)
1493 /* --------------------------------------------------------------------------
1495 -------------------------------------------------------------------------- */
1496 /* On *Step, we attempt to mimic the X11 platform here, down to installing an
1497 X11 rgb.txt-compatible color list in Emacs.clr (see ns_term_init()).
1498 See: http://thread.gmane.org/gmane.emacs.devel/113050/focus=113272). */
1501 static char hex[20];
1503 float r = -1.0, g, b;
1504 NSString *nsname = [NSString stringWithUTF8String: name];
1506 /*fprintf (stderr, "ns_get_color: '%s'\n", name); */
1509 if ([nsname isEqualToString: @"ns_selection_color"])
1511 nsname = ns_selection_color;
1512 name = [ns_selection_color UTF8String];
1515 /* First, check for some sort of numeric specification. */
1518 if (name[0] == '0' || name[0] == '1' || name[0] == '.') /* RGB decimal */
1520 NSScanner *scanner = [NSScanner scannerWithString: nsname];
1521 [scanner scanFloat: &r];
1522 [scanner scanFloat: &g];
1523 [scanner scanFloat: &b];
1525 else if (!strncmp(name, "rgb:", 4)) /* A newer X11 format -- rgb:r/g/b */
1526 scaling = (snprintf (hex, sizeof hex, "%s", name + 4) - 2) / 3;
1527 else if (name[0] == '#') /* An old X11 format; convert to newer */
1529 int len = (strlen(name) - 1);
1530 int start = (len % 3 == 0) ? 1 : len / 4 + 1;
1532 scaling = strlen(name+start) / 3;
1533 for (i = 0; i < 3; i++)
1534 sprintf (hex + i * (scaling + 1), "%.*s/", scaling,
1535 name + start + i * scaling);
1536 hex[3 * (scaling + 1) - 1] = '\0';
1542 float fscale = scaling == 4 ? 65535.0 : (scaling == 2 ? 255.0 : 15.0);
1543 if (sscanf (hex, "%x/%x/%x", &rr, &gg, &bb))
1553 *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0];
1558 /* Otherwise, color is expected to be from a list */
1560 NSEnumerator *lenum, *cenum;
1564 #ifdef NS_IMPL_GNUSTEP
1565 /* XXX: who is wrong, the requestor or the implementation? */
1566 if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
1568 nsname = @"highlightColor";
1571 lenum = [[NSColorList availableColorLists] objectEnumerator];
1572 while ( (clist = [lenum nextObject]) && new == nil)
1574 cenum = [[clist allKeys] objectEnumerator];
1575 while ( (name = [cenum nextObject]) && new == nil )
1577 if ([name compare: nsname
1578 options: NSCaseInsensitiveSearch] == NSOrderedSame )
1579 new = [clist colorWithKey: name];
1585 *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
1592 ns_lisp_to_color (Lisp_Object color, NSColor **col)
1593 /* --------------------------------------------------------------------------
1594 Convert a Lisp string object to a NS color
1595 -------------------------------------------------------------------------- */
1597 NSTRACE (ns_lisp_to_color);
1598 if (STRINGP (color))
1599 return ns_get_color (SSDATA (color), col);
1600 else if (SYMBOLP (color))
1601 return ns_get_color (SSDATA (SYMBOL_NAME (color)), col);
1607 ns_color_to_lisp (NSColor *col)
1608 /* --------------------------------------------------------------------------
1609 Convert a color to a lisp string with the RGB equivalent
1610 -------------------------------------------------------------------------- */
1612 CGFloat red, green, blue, alpha, gray;
1615 NSTRACE (ns_color_to_lisp);
1618 if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
1620 if ((str =[[col colorNameComponent] UTF8String]))
1623 return build_string ((char *)str);
1626 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
1627 getRed: &red green: &green blue: &blue alpha: &alpha];
1628 if (red ==green && red ==blue)
1630 [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
1631 getWhite: &gray alpha: &alpha];
1632 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1633 lrint (gray * 0xff), lrint (gray * 0xff), lrint (gray * 0xff));
1635 return build_string (buf);
1638 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1639 lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
1642 return build_string (buf);
1647 ns_query_color(void *col, XColor *color_def, int setPixel)
1648 /* --------------------------------------------------------------------------
1649 Get ARGB values out of NSColor col and put them into color_def.
1650 If setPixel, set the pixel to a concatenated version.
1651 and set color_def pixel to the resulting index.
1652 -------------------------------------------------------------------------- */
1656 [((NSColor *)col) getRed: &r green: &g blue: &b alpha: &a];
1657 color_def->red = r * 65535;
1658 color_def->green = g * 65535;
1659 color_def->blue = b * 65535;
1661 if (setPixel == YES)
1663 = ARGB_TO_ULONG((int)(a*255),
1664 (int)(r*255), (int)(g*255), (int)(b*255));
1669 ns_defined_color (struct frame *f,
1674 /* --------------------------------------------------------------------------
1675 Return true if named color found, and set color_def rgb accordingly.
1676 If makeIndex and alloc are nonzero put the color in the color_table,
1677 and set color_def pixel to the resulting index.
1678 If makeIndex is zero, set color_def pixel to ARGB.
1679 Return false if not found
1680 -------------------------------------------------------------------------- */
1683 NSTRACE (ns_defined_color);
1686 if (ns_get_color (name, &col) != 0) /* Color not found */
1691 if (makeIndex && alloc)
1692 color_def->pixel = ns_index_color (col, f);
1693 ns_query_color (col, color_def, !makeIndex);
1700 ns_get_rgb_color (struct frame *f, float r, float g, float b, float a)
1701 /* --------------------------------------------------------------------------
1702 return an autoreleased RGB color
1703 -------------------------------------------------------------------------- */
1705 /*static int c = 1; fprintf (stderr, "color request %d\n", c++); */
1706 if (r < 0.0) r = 0.0;
1707 else if (r > 1.0) r = 1.0;
1708 if (g < 0.0) g = 0.0;
1709 else if (g > 1.0) g = 1.0;
1710 if (b < 0.0) b = 0.0;
1711 else if (b > 1.0) b = 1.0;
1712 if (a < 0.0) a = 0.0;
1713 else if (a > 1.0) a = 1.0;
1714 return (unsigned long) ns_index_color(
1715 [NSColor colorWithCalibratedRed: r green: g blue: b alpha: a], f);
1720 x_set_frame_alpha (struct frame *f)
1721 /* --------------------------------------------------------------------------
1722 change the entire-frame transparency
1723 -------------------------------------------------------------------------- */
1725 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1726 EmacsView *view = FRAME_NS_VIEW (f);
1728 double alpha_min = 1.0;
1730 if (dpyinfo->x_highlight_frame == f)
1731 alpha = f->alpha[0];
1733 alpha = f->alpha[1];
1735 if (FLOATP (Vframe_alpha_lower_limit))
1736 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
1737 else if (INTEGERP (Vframe_alpha_lower_limit))
1738 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
1742 else if (1.0 < alpha)
1744 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
1747 #ifdef NS_IMPL_COCOA
1748 [[view window] setAlphaValue: alpha];
1753 /* ==========================================================================
1757 ========================================================================== */
1761 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
1762 /* --------------------------------------------------------------------------
1763 Programmatically reposition mouse pointer in pixel coordinates
1764 -------------------------------------------------------------------------- */
1766 NSTRACE (x_set_mouse_pixel_position);
1769 /* FIXME: this does not work, and what about GNUstep? */
1770 #ifdef NS_IMPL_COCOA
1771 [FRAME_NS_VIEW (f) lockFocus];
1772 PSsetmouse ((float)pix_x, (float)pix_y);
1773 [FRAME_NS_VIEW (f) unlockFocus];
1780 x_set_mouse_position (struct frame *f, int h, int v)
1781 /* --------------------------------------------------------------------------
1782 Programmatically reposition mouse pointer in character coordinates
1783 -------------------------------------------------------------------------- */
1787 pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2;
1788 pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2;
1790 if (pix_x < 0) pix_x = 0;
1791 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
1793 if (pix_y < 0) pix_y = 0;
1794 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
1796 x_set_mouse_pixel_position (f, pix_x, pix_y);
1801 note_mouse_movement (struct frame *frame, float x, float y)
1802 /* ------------------------------------------------------------------------
1803 Called by EmacsView on mouseMovement events. Passes on
1804 to emacs mainstream code if we moved off of a rect of interest
1805 known as last_mouse_glyph.
1806 ------------------------------------------------------------------------ */
1808 // NSTRACE (note_mouse_movement);
1810 XSETFRAME (last_mouse_motion_frame, frame);
1812 /* Note, this doesn't get called for enter/leave, since we don't have a
1813 position. Those are taken care of in the corresponding NSView methods. */
1815 /* has movement gone beyond last rect we were tracking? */
1816 if (x < last_mouse_glyph.origin.x ||
1817 x >= (last_mouse_glyph.origin.x + last_mouse_glyph.size.width) ||
1818 y < last_mouse_glyph.origin.y ||
1819 y >= (last_mouse_glyph.origin.y + last_mouse_glyph.size.height))
1821 ns_update_begin(frame);
1822 frame->mouse_moved = 1;
1823 note_mouse_highlight (frame, x, y);
1824 remember_mouse_glyph (frame, x, y, &last_mouse_glyph);
1825 ns_update_end(frame);
1834 ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
1835 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
1837 /* --------------------------------------------------------------------------
1838 External (hook): inform emacs about mouse position and hit parts.
1839 If a scrollbar is being dragged, set bar_window, part, x, y, time.
1840 x & y should be position in the scrollbar (the whole bar, not the handle)
1841 and length of scrollbar respectively
1842 -------------------------------------------------------------------------- */
1846 Lisp_Object frame, tail;
1848 struct ns_display_info *dpyinfo;
1850 NSTRACE (ns_mouse_position);
1854 fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n");
1858 dpyinfo = FRAME_NS_DISPLAY_INFO (*fp);
1862 if (last_mouse_scroll_bar != nil && insist == 0)
1864 /* TODO: we do not use this path at the moment because drag events will
1865 go directly to the EmacsScroller. Leaving code in for now. */
1866 [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window
1868 if (time) *time = last_mouse_movement_time;
1869 last_mouse_scroll_bar = nil;
1873 /* Clear the mouse-moved flag for every frame on this display. */
1874 FOR_EACH_FRAME (tail, frame)
1875 if (FRAME_NS_P (XFRAME (frame))
1876 && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
1877 XFRAME (frame)->mouse_moved = 0;
1879 last_mouse_scroll_bar = nil;
1880 if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame))
1881 f = last_mouse_frame;
1883 f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame
1884 : SELECTED_FRAME ();
1886 if (f && FRAME_NS_P (f))
1888 view = FRAME_NS_VIEW (*fp);
1890 position = [[view window] mouseLocationOutsideOfEventStream];
1891 position = [view convertPoint: position fromView: nil];
1892 remember_mouse_glyph (f, position.x, position.y, &last_mouse_glyph);
1893 /*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
1895 if (bar_window) *bar_window = Qnil;
1896 if (part) *part = 0; /*scroll_bar_handle; */
1898 if (x) XSETINT (*x, lrint (position.x));
1899 if (y) XSETINT (*y, lrint (position.y));
1900 if (time) *time = last_mouse_movement_time;
1910 ns_frame_up_to_date (struct frame *f)
1911 /* --------------------------------------------------------------------------
1912 External (hook): Fix up mouse highlighting right after a full update.
1913 Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls.
1914 -------------------------------------------------------------------------- */
1916 NSTRACE (ns_frame_up_to_date);
1920 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
1921 if (f == hlinfo->mouse_face_mouse_frame)
1925 if (hlinfo->mouse_face_mouse_frame)
1926 note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
1927 hlinfo->mouse_face_mouse_x,
1928 hlinfo->mouse_face_mouse_y);
1937 ns_define_frame_cursor (struct frame *f, Cursor cursor)
1938 /* --------------------------------------------------------------------------
1939 External (RIF): set frame mouse pointer type.
1940 -------------------------------------------------------------------------- */
1942 NSTRACE (ns_define_frame_cursor);
1943 if (FRAME_POINTER_TYPE (f) != cursor)
1945 EmacsView *view = FRAME_NS_VIEW (f);
1946 FRAME_POINTER_TYPE (f) = cursor;
1947 [[view window] invalidateCursorRectsForView: view];
1948 /* Redisplay assumes this function also draws the changed frame
1949 cursor, but this function doesn't, so do it explicitly. */
1950 x_update_cursor (f, 1);
1956 /* ==========================================================================
1960 ========================================================================== */
1964 ns_convert_key (unsigned code)
1965 /* --------------------------------------------------------------------------
1966 Internal call used by NSView-keyDown.
1967 -------------------------------------------------------------------------- */
1969 const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym)
1970 / sizeof (convert_ns_to_X_keysym[0]));
1972 /* An array would be faster, but less easy to read. */
1973 for (keysym = 0; keysym < last_keysym; keysym += 2)
1974 if (code == convert_ns_to_X_keysym[keysym])
1975 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
1977 /* if decide to use keyCode and Carbon table, use this line:
1978 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
1983 x_get_keysym_name (int keysym)
1984 /* --------------------------------------------------------------------------
1985 Called by keyboard.c. Not sure if the return val is important, except
1987 -------------------------------------------------------------------------- */
1989 static char value[16];
1990 NSTRACE (x_get_keysym_name);
1991 sprintf (value, "%d", keysym);
1997 /* ==========================================================================
1999 Block drawing operations
2001 ========================================================================== */
2005 ns_redraw_scroll_bars (struct frame *f)
2009 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
2010 NSTRACE (ns_redraw_scroll_bars);
2011 for (i =[subviews count]-1; i >= 0; i--)
2013 view = [subviews objectAtIndex: i];
2014 if (![view isKindOfClass: [EmacsScroller class]]) continue;
2021 ns_clear_frame (struct frame *f)
2022 /* --------------------------------------------------------------------------
2023 External (hook): Erase the entire frame
2024 -------------------------------------------------------------------------- */
2026 NSView *view = FRAME_NS_VIEW (f);
2029 NSTRACE (ns_clear_frame);
2031 /* comes on initial frame because we have
2032 after-make-frame-functions = select-frame */
2033 if (!FRAME_DEFAULT_FACE (f))
2036 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2038 output_cursor.hpos = output_cursor.vpos = 0;
2039 output_cursor.x = -1;
2044 ns_focus (f, &r, 1);
2045 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
2049 /* as of 2006/11 or so this is now needed */
2050 ns_redraw_scroll_bars (f);
2056 ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
2057 /* --------------------------------------------------------------------------
2058 External (RIF): Clear section of frame
2059 -------------------------------------------------------------------------- */
2061 NSRect r = NSMakeRect (x, y, width, height);
2062 NSView *view = FRAME_NS_VIEW (f);
2063 struct face *face = FRAME_DEFAULT_FACE (f);
2068 NSTRACE (ns_clear_frame_area);
2070 r = NSIntersectionRect (r, [view frame]);
2071 ns_focus (f, &r, 1);
2072 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
2082 ns_scroll_run (struct window *w, struct run *run)
2083 /* --------------------------------------------------------------------------
2084 External (RIF): Insert or delete n lines at line vpos
2085 -------------------------------------------------------------------------- */
2087 struct frame *f = XFRAME (w->frame);
2088 int x, y, width, height, from_y, to_y, bottom_y;
2090 NSTRACE (ns_scroll_run);
2092 /* begin copy from other terms */
2093 /* Get frame-relative bounding box of the text display area of W,
2094 without mode lines. Include in this box the left and right
2096 window_box (w, -1, &x, &y, &width, &height);
2098 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2099 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2100 bottom_y = y + height;
2104 /* Scrolling up. Make sure we don't copy part of the mode
2105 line at the bottom. */
2106 if (from_y + run->height > bottom_y)
2107 height = bottom_y - from_y;
2109 height = run->height;
2113 /* Scrolling down. Make sure we don't copy over the mode line.
2115 if (to_y + run->height > bottom_y)
2116 height = bottom_y - to_y;
2118 height = run->height;
2120 /* end copy from other terms */
2131 NSRect srcRect = NSMakeRect (x, from_y, width, height);
2132 NSRect dstRect = NSMakeRect (x, to_y, width, height);
2133 NSPoint dstOrigin = NSMakePoint (x, to_y);
2135 ns_focus (f, &dstRect, 1);
2136 NSCopyBits (0, srcRect , dstOrigin);
2145 ns_after_update_window_line (struct glyph_row *desired_row)
2146 /* --------------------------------------------------------------------------
2147 External (RIF): preparatory to fringe update after text was updated
2148 -------------------------------------------------------------------------- */
2150 struct window *w = updated_window;
2154 NSTRACE (ns_after_update_window_line);
2156 /* begin copy from other terms */
2159 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2160 desired_row->redraw_fringe_bitmaps_p = 1;
2162 /* When a window has disappeared, make sure that no rest of
2163 full-width rows stays visible in the internal border. */
2164 if (windows_or_buffers_changed
2165 && desired_row->full_width_p
2166 && (f = XFRAME (w->frame),
2167 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2169 && (height = desired_row->visible_height,
2172 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2175 ns_clear_frame_area (f, 0, y, width, height);
2176 ns_clear_frame_area (f,
2177 FRAME_PIXEL_WIDTH (f) - width,
2185 ns_shift_glyphs_for_insert (struct frame *f,
2186 int x, int y, int width, int height,
2188 /* --------------------------------------------------------------------------
2189 External (RIF): copy an area horizontally, don't worry about clearing src
2190 -------------------------------------------------------------------------- */
2192 NSRect srcRect = NSMakeRect (x, y, width, height);
2193 NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
2194 NSPoint dstOrigin = dstRect.origin;
2196 NSTRACE (ns_shift_glyphs_for_insert);
2198 ns_focus (f, &dstRect, 1);
2199 NSCopyBits (0, srcRect, dstOrigin);
2205 /* ==========================================================================
2207 Character encoding and metrics
2209 ========================================================================== */
2213 ns_compute_glyph_string_overhangs (struct glyph_string *s)
2214 /* --------------------------------------------------------------------------
2215 External (RIF); compute left/right overhang of whole string and set in s
2216 -------------------------------------------------------------------------- */
2218 struct font *font = s->font;
2222 struct font_metrics metrics;
2223 unsigned int codes[2];
2224 codes[0] = *(s->char2b);
2225 codes[1] = *(s->char2b + s->nchars - 1);
2227 font->driver->text_extents (font, codes, 2, &metrics);
2228 s->left_overhang = -metrics.lbearing;
2230 = metrics.rbearing > metrics.width
2231 ? metrics.rbearing - metrics.width : 0;
2235 s->left_overhang = 0;
2236 s->right_overhang = ((struct nsfont_info *)font)->ital ?
2237 FONT_HEIGHT (font) * 0.2 : 0;
2243 /* ==========================================================================
2245 Fringe and cursor drawing
2247 ========================================================================== */
2250 extern int max_used_fringe_bitmap;
2252 ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2253 struct draw_fringe_bitmap_params *p)
2254 /* --------------------------------------------------------------------------
2255 External (RIF); fringe-related
2256 -------------------------------------------------------------------------- */
2258 struct frame *f = XFRAME (WINDOW_FRAME (w));
2259 struct face *face = p->face;
2261 static EmacsImage **bimgs = NULL;
2262 static int nBimgs = 0;
2264 /* grow bimgs if needed */
2265 if (nBimgs < max_used_fringe_bitmap)
2267 bimgs = xrealloc (bimgs, max_used_fringe_bitmap * sizeof *bimgs);
2268 memset (bimgs + nBimgs, 0,
2269 (max_used_fringe_bitmap - nBimgs) * sizeof *bimgs);
2270 nBimgs = max_used_fringe_bitmap;
2273 /* Must clip because of partially visible lines. */
2274 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2275 ns_clip_to_row (w, row, -1, YES);
2279 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2281 /* If the fringe is adjacent to the left (right) scroll bar of a
2282 leftmost (rightmost, respectively) window, then extend its
2283 background to the gap between the fringe and the bar. */
2284 if ((WINDOW_LEFTMOST_P (w)
2285 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2286 || (WINDOW_RIGHTMOST_P (w)
2287 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2289 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2293 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
2294 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2295 * FRAME_COLUMN_WIDTH (f));
2299 /* Bitmap fills the fringe. */
2300 if (bar_area_x + bar_area_width == p->x)
2301 bx = bar_area_x + sb_width;
2302 else if (p->x + p->wd == bar_area_x)
2306 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2308 nx = bar_area_width - sb_width;
2309 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2311 ny = row->visible_height;
2316 if (bar_area_x + bar_area_width == bx)
2318 bx = bar_area_x + sb_width;
2319 nx += bar_area_width - sb_width;
2321 else if (bx + nx == bar_area_x)
2322 nx += bar_area_width - sb_width;
2327 if (bx >= 0 && nx > 0)
2329 NSRect r = NSMakeRect (bx, by, nx, ny);
2331 [ns_lookup_indexed_color (face->background, f) set];
2338 NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h);
2339 EmacsImage *img = bimgs[p->which - 1];
2343 unsigned short *bits = p->bits + p->dh;
2346 unsigned char *cbits = xmalloc (len);
2348 for (i = 0; i < len; i++)
2349 cbits[i] = ~(bits[i] & 0xff);
2350 img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
2352 bimgs[p->which - 1] = img;
2357 /* Since we composite the bitmap instead of just blitting it, we need
2358 to erase the whole background. */
2359 [ns_lookup_indexed_color(face->background, f) set];
2361 [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)];
2362 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
2364 fromRect: NSZeroRect
2365 operation: NSCompositeSourceOver
2371 NSPoint pt = r.origin;
2373 [img compositeToPoint: pt operation: NSCompositeSourceOver];
2382 ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2383 int x, int y, int cursor_type, int cursor_width,
2384 int on_p, int active_p)
2385 /* --------------------------------------------------------------------------
2386 External call (RIF): draw cursor.
2387 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
2388 -------------------------------------------------------------------------- */
2391 int fx, fy, h, cursor_height;
2392 struct frame *f = WINDOW_XFRAME (w);
2393 struct glyph *phys_cursor_glyph;
2395 struct glyph *cursor_glyph;
2397 NSColor *hollow_color = FRAME_BACKGROUND_COLOR (f);
2399 /* If cursor is out of bounds, don't draw garbage. This can happen
2400 in mini-buffer windows when switching between echo area glyphs
2403 NSTRACE (dumpcursor);
2408 w->phys_cursor_type = cursor_type;
2409 w->phys_cursor_on_p = on_p;
2411 if (cursor_type == NO_CURSOR)
2413 w->phys_cursor_width = 0;
2417 if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
2419 if (glyph_row->exact_window_width_line_p
2420 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
2422 glyph_row->cursor_in_fringe_p = 1;
2423 draw_fringe_bitmap (w, glyph_row, 0);
2428 /* We draw the cursor (with NSRectFill), then draw the glyph on top
2429 (other terminals do it the other way round). We must set
2430 w->phys_cursor_width to the cursor width. For bar cursors, that
2431 is CURSOR_WIDTH; for box cursors, it is the glyph width. */
2432 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
2434 /* The above get_phys_cursor_geometry call set w->phys_cursor_width
2435 to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */
2436 if (cursor_type == BAR_CURSOR)
2438 if (cursor_width < 1)
2439 cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
2440 w->phys_cursor_width = cursor_width;
2442 /* If we have an HBAR, "cursor_width" MAY specify height. */
2443 else if (cursor_type == HBAR_CURSOR)
2445 cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
2446 fy += h - cursor_height;
2450 r.origin.x = fx, r.origin.y = fy;
2452 r.size.width = w->phys_cursor_width;
2454 /* TODO: only needed in rare cases with last-resort font in HELLO..
2455 should we do this more efficiently? */
2456 ns_clip_to_row (w, glyph_row, -1, NO); /* do ns_focus(f, &r, 1); if remove */
2459 face = FACE_FROM_ID (f, phys_cursor_glyph->face_id);
2460 if (face && NS_FACE_BACKGROUND (face)
2461 == ns_index_color (FRAME_CURSOR_COLOR (f), f))
2463 [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
2464 hollow_color = FRAME_CURSOR_COLOR (f);
2467 [FRAME_CURSOR_COLOR (f) set];
2469 #ifdef NS_IMPL_COCOA
2470 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
2471 atomic. Cleaner ways of doing this should be investigated.
2472 One way would be to set a global variable DRAWING_CURSOR
2473 when making the call to draw_phys..(), don't focus in that
2474 case, then move the ns_unfocus() here after that call. */
2475 NSDisableScreenUpdates ();
2478 switch (cursor_type)
2482 case FILLED_BOX_CURSOR:
2485 case HOLLOW_BOX_CURSOR:
2488 NSRectFill (NSInsetRect (r, 1, 1));
2489 [FRAME_CURSOR_COLOR (f) set];
2496 /* If the character under cursor is R2L, draw the bar cursor
2497 on the right of its glyph, rather than on the left. */
2498 cursor_glyph = get_phys_cursor_glyph (w);
2499 if ((cursor_glyph->resolved_level & 1) != 0)
2500 s.origin.x += cursor_glyph->pixel_width - s.size.width;
2507 /* draw the character under the cursor */
2508 if (cursor_type != NO_CURSOR)
2509 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2511 #ifdef NS_IMPL_COCOA
2512 NSEnableScreenUpdates ();
2519 ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2520 /* --------------------------------------------------------------------------
2521 External (RIF): Draw a vertical line.
2522 -------------------------------------------------------------------------- */
2524 struct frame *f = XFRAME (WINDOW_FRAME (w));
2526 NSRect r = NSMakeRect (x, y0, 1, y1-y0);
2528 NSTRACE (ns_draw_vertical_window_border);
2530 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2532 [ns_lookup_indexed_color(face->foreground, f) set];
2534 ns_focus (f, &r, 1);
2541 show_hourglass (struct atimer *timer)
2543 if (hourglass_shown_p)
2548 /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */
2550 hourglass_shown_p = 1;
2556 hide_hourglass (void)
2558 if (!hourglass_shown_p)
2563 /* TODO: remove NSProgressIndicator from all frames */
2565 hourglass_shown_p = 0;
2571 /* ==========================================================================
2573 Glyph drawing operations
2575 ========================================================================== */
2578 ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2579 /* --------------------------------------------------------------------------
2580 Wrapper utility to account for internal border width on full-width lines,
2581 and allow top full-width rows to hit the frame top. nr should be pointer
2582 to two successive NSRects. Number of rects actually used is returned.
2583 -------------------------------------------------------------------------- */
2585 int n = get_glyph_string_clip_rects (s, nr, 2);
2589 /* --------------------------------------------------------------------
2590 Draw a wavy line under glyph string s. The wave fills wave_height
2597 wave_height = 3 | * * * *
2598 --------------------------------------------------------------------- */
2601 ns_draw_underwave (struct glyph_string *s, CGFloat width, CGFloat x)
2603 int wave_height = 3, wave_length = 2;
2604 int y, dx, dy, odd, xmax;
2609 dy = wave_height - 1;
2610 y = s->ybase - wave_height + 3;
2613 /* Find and set clipping rectangle */
2614 waveClip = NSMakeRect (x, y, width, wave_height);
2615 [[NSGraphicsContext currentContext] saveGraphicsState];
2616 NSRectClip (waveClip);
2618 /* Draw the waves */
2619 a.x = x - ((int)(x) % dx) + 0.5;
2621 odd = (int)(a.x/dx) % 2;
2622 a.y = b.y = y + 0.5;
2631 [NSBezierPath strokeLineFromPoint:a toPoint:b];
2632 a.x = b.x, a.y = b.y;
2633 b.x += dx, b.y = y + 0.5 + odd*dy;
2637 /* Restore previous clipping rectangle(s) */
2638 [[NSGraphicsContext currentContext] restoreGraphicsState];
2644 ns_draw_text_decoration (struct glyph_string *s, struct face *face,
2645 NSColor *defaultCol, CGFloat width, CGFloat x)
2646 /* --------------------------------------------------------------------------
2647 Draw underline, overline, and strike-through on glyph string s.
2648 -------------------------------------------------------------------------- */
2650 if (s->for_overlaps)
2654 if (face->underline_p)
2656 if (s->face->underline_type == FACE_UNDER_WAVE)
2658 if (face->underline_defaulted_p)
2661 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2663 ns_draw_underwave (s, width, x);
2665 else if (s->face->underline_type == FACE_UNDER_LINE)
2669 unsigned long thickness, position;
2671 /* If the prev was underlined, match its appearance. */
2672 if (s->prev && s->prev->face->underline_p
2673 && s->prev->face->underline_type == FACE_UNDER_LINE
2674 && s->prev->underline_thickness > 0)
2676 thickness = s->prev->underline_thickness;
2677 position = s->prev->underline_position;
2682 unsigned long descent;
2685 descent = s->y + s->height - s->ybase;
2687 /* Use underline thickness of font, defaulting to 1. */
2688 thickness = (font && font->underline_thickness > 0)
2689 ? font->underline_thickness : 1;
2691 /* Determine the offset of underlining from the baseline. */
2692 if (x_underline_at_descent_line)
2693 position = descent - thickness;
2694 else if (x_use_underline_position_properties
2695 && font && font->underline_position >= 0)
2696 position = font->underline_position;
2698 position = lround (font->descent / 2);
2700 position = underline_minimum_offset;
2702 position = max (position, underline_minimum_offset);
2704 /* Ensure underlining is not cropped. */
2705 if (descent <= position)
2707 position = descent - 1;
2710 else if (descent < position + thickness)
2714 s->underline_thickness = thickness;
2715 s->underline_position = position;
2717 r = NSMakeRect (x, s->ybase + position, width, thickness);
2719 if (face->underline_defaulted_p)
2722 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2726 /* Do overline. We follow other terms in using a thickness of 1
2727 and ignoring overline_margin. */
2728 if (face->overline_p)
2731 r = NSMakeRect (x, s->y, width, 1);
2733 if (face->overline_color_defaulted_p)
2736 [ns_lookup_indexed_color (face->overline_color, s->f) set];
2740 /* Do strike-through. We follow other terms for thickness and
2741 vertical position.*/
2742 if (face->strike_through_p)
2747 dy = lrint ((s->height - 1) / 2);
2748 r = NSMakeRect (x, s->y + dy, width, 1);
2750 if (face->strike_through_color_defaulted_p)
2753 [ns_lookup_indexed_color (face->strike_through_color, s->f) set];
2759 ns_draw_box (NSRect r, float thickness, NSColor *col, char left_p, char right_p)
2760 /* --------------------------------------------------------------------------
2761 Draw an unfilled rect inside r, optionally leaving left and/or right open.
2762 Note we can't just use an NSDrawRect command, because of the possibility
2763 of some sides not being drawn, and because the rect will be filled.
2764 -------------------------------------------------------------------------- */
2770 s.size.height = thickness;
2772 s.origin.y += r.size.height - thickness;
2775 s.size.height = r.size.height;
2776 s.origin.y = r.origin.y;
2778 /* left, right (optional) */
2779 s.size.width = thickness;
2784 s.origin.x += r.size.width - thickness;
2791 ns_draw_relief (NSRect r, int thickness, char raised_p,
2792 char top_p, char bottom_p, char left_p, char right_p,
2793 struct glyph_string *s)
2794 /* --------------------------------------------------------------------------
2795 Draw a relief rect inside r, optionally leaving some sides open.
2796 Note we can't just use an NSDrawBezel command, because of the possibility
2797 of some sides not being drawn, and because the rect will be filled.
2798 -------------------------------------------------------------------------- */
2800 static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
2801 NSColor *newBaseCol = nil;
2804 NSTRACE (ns_draw_relief);
2808 if (s->face->use_box_color_for_shadows_p)
2810 newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f);
2812 /* else if (s->first_glyph->type == IMAGE_GLYPH
2814 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2816 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
2820 newBaseCol = ns_lookup_indexed_color (s->face->background, s->f);
2823 if (newBaseCol == nil)
2824 newBaseCol = [NSColor grayColor];
2826 if (newBaseCol != baseCol) /* TODO: better check */
2829 baseCol = [newBaseCol retain];
2831 lightCol = [[baseCol highlightWithLevel: 0.2] retain];
2833 darkCol = [[baseCol shadowWithLevel: 0.3] retain];
2836 [(raised_p ? lightCol : darkCol) set];
2838 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
2841 sr.size.height = thickness;
2842 if (top_p) NSRectFill (sr);
2845 sr.size.height = r.size.height;
2846 sr.size.width = thickness;
2847 if (left_p) NSRectFill (sr);
2849 [(raised_p ? darkCol : lightCol) set];
2852 sr.size.width = r.size.width;
2853 sr.size.height = thickness;
2854 sr.origin.y += r.size.height - thickness;
2855 if (bottom_p) NSRectFill (sr);
2858 sr.size.height = r.size.height;
2859 sr.origin.y = r.origin.y;
2860 sr.size.width = thickness;
2861 sr.origin.x += r.size.width - thickness;
2862 if (right_p) NSRectFill (sr);
2867 ns_dumpglyphs_box_or_relief (struct glyph_string *s)
2868 /* --------------------------------------------------------------------------
2869 Function modeled after x_draw_glyph_string_box ().
2870 Sets up parameters for drawing.
2871 -------------------------------------------------------------------------- */
2873 int right_x, last_x;
2874 char left_p, right_p;
2875 struct glyph *last_glyph;
2880 if (s->hl == DRAW_MOUSE_FACE)
2882 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2884 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2889 thickness = face->box_line_width;
2891 NSTRACE (ns_dumpglyphs_box_or_relief);
2893 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2894 ? WINDOW_RIGHT_EDGE_X (s->w)
2895 : window_box_right (s->w, s->area));
2896 last_glyph = (s->cmp || s->img
2897 ? s->first_glyph : s->first_glyph + s->nchars-1);
2899 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2900 ? last_x - 1 : min (last_x, s->x + s->background_width) - 1));
2902 left_p = (s->first_glyph->left_box_line_p
2903 || (s->hl == DRAW_MOUSE_FACE
2904 && (s->prev == NULL || s->prev->hl != s->hl)));
2905 right_p = (last_glyph->right_box_line_p
2906 || (s->hl == DRAW_MOUSE_FACE
2907 && (s->next == NULL || s->next->hl != s->hl)));
2909 r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
2911 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
2912 if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
2914 ns_draw_box (r, abs (thickness),
2915 ns_lookup_indexed_color (face->box_color, s->f),
2920 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
2921 1, 1, left_p, right_p, s);
2927 ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
2928 /* --------------------------------------------------------------------------
2929 Modeled after x_draw_glyph_string_background, which draws BG in
2930 certain cases. Others are left to the text rendering routine.
2931 -------------------------------------------------------------------------- */
2933 NSTRACE (ns_maybe_dumpglyphs_background);
2935 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
2937 int box_line_width = max (s->face->box_line_width, 0);
2938 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2939 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
2942 if (s->hl == DRAW_MOUSE_FACE)
2944 face = FACE_FROM_ID (s->f,
2945 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2947 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2950 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2952 [(NS_FACE_BACKGROUND (face) != 0
2953 ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
2954 : FRAME_BACKGROUND_COLOR (s->f)) set];
2957 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (s->f);
2958 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
2961 if (s->hl != DRAW_CURSOR)
2963 NSRect r = NSMakeRect (s->x, s->y + box_line_width,
2964 s->background_width,
2965 s->height-2*box_line_width);
2969 s->background_filled_p = 1;
2976 ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
2977 /* --------------------------------------------------------------------------
2978 Renders an image and associated borders.
2979 -------------------------------------------------------------------------- */
2981 EmacsImage *img = s->img->pixmap;
2982 int box_line_vwidth = max (s->face->box_line_width, 0);
2983 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2984 int bg_x, bg_y, bg_height;
2991 NSTRACE (ns_dumpglyphs_image);
2993 if (s->face->box != FACE_NO_BOX
2994 && s->first_glyph->left_box_line_p && s->slice.x == 0)
2995 x += abs (s->face->box_line_width);
2998 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
2999 bg_height = s->height;
3000 /* other terms have this, but was causing problems w/tabbar mode */
3001 /* - 2 * box_line_vwidth; */
3003 if (s->slice.x == 0) x += s->img->hmargin;
3004 if (s->slice.y == 0) y += s->img->vmargin;
3006 /* Draw BG: if we need larger area than image itself cleared, do that,
3007 otherwise, since we composite the image under NS (instead of mucking
3008 with its background color), we must clear just the image area. */
3009 if (s->hl == DRAW_MOUSE_FACE)
3011 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3013 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3016 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3018 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set];
3020 if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin
3021 || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width)
3023 br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height);
3024 s->background_filled_p = 1;
3028 br = NSMakeRect (x, y, s->slice.width, s->slice.height);
3033 /* Draw the image.. do we need to draw placeholder if img ==nil? */
3036 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
3037 NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height);
3038 NSRect ir = NSMakeRect (s->slice.x, s->slice.y,
3039 s->slice.width, s->slice.height);
3042 operation: NSCompositeSourceOver
3047 [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
3048 operation: NSCompositeSourceOver];
3052 if (s->hl == DRAW_CURSOR)
3054 [FRAME_CURSOR_COLOR (s->f) set];
3055 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3056 tdCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3058 /* Currently on NS img->mask is always 0. Since
3059 get_window_cursor_type specifies a hollow box cursor when on
3060 a non-masked image we never reach this clause. But we put it
3061 in in anticipation of better support for image masks on
3063 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3067 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3070 /* Draw underline, overline, strike-through. */
3071 ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x);
3073 /* Draw relief, if requested */
3074 if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
3076 if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
3078 th = tool_bar_button_relief >= 0 ?
3079 tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3080 raised_p = (s->hl == DRAW_IMAGE_RAISED);
3084 th = abs (s->img->relief);
3085 raised_p = (s->img->relief > 0);
3088 r.origin.x = x - th;
3089 r.origin.y = y - th;
3090 r.size.width = s->slice.width + 2*th-1;
3091 r.size.height = s->slice.height + 2*th-1;
3092 ns_draw_relief (r, th, raised_p,
3094 s->slice.y + s->slice.height == s->img->height,
3096 s->slice.x + s->slice.width == s->img->width, s);
3099 /* If there is no mask, the background won't be seen,
3100 so draw a rectangle on the image for the cursor.
3101 Do this for all images, getting transparency right is not reliable. */
3102 if (s->hl == DRAW_CURSOR)
3104 int thickness = abs (s->img->relief);
3105 if (thickness == 0) thickness = 1;
3106 ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
3112 ns_dumpglyphs_stretch (struct glyph_string *s)
3117 NSColor *fgCol, *bgCol;
3119 if (!s->background_filled_p)
3121 n = ns_get_glyph_string_clip_rect (s, r);
3122 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
3124 ns_focus (s->f, r, n);
3126 if (s->hl == DRAW_MOUSE_FACE)
3128 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3130 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3133 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3135 bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3136 fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3138 for (i = 0; i < n; ++i)
3140 if (!s->row->full_width_p)
3142 int overrun, leftoverrun;
3144 /* truncate to avoid overwriting fringe and/or scrollbar */
3145 overrun = max (0, (s->x + s->background_width)
3146 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
3147 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
3148 r[i].size.width -= overrun;
3150 /* truncate to avoid overwriting to left of the window box */
3151 leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
3152 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
3154 if (leftoverrun > 0)
3156 r[i].origin.x += leftoverrun;
3157 r[i].size.width -= leftoverrun;
3160 /* XXX: Try to work between problem where a stretch glyph on
3161 a partially-visible bottom row will clear part of the
3162 modeline, and another where list-buffers headers and similar
3163 rows erroneously have visible_height set to 0. Not sure
3164 where this is coming from as other terms seem not to show. */
3165 r[i].size.height = min (s->height, s->row->visible_height);
3170 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
3171 overwriting cursor (usually when cursor on a tab) */
3172 if (s->hl == DRAW_CURSOR)
3177 width = s->w->phys_cursor_width;
3178 r[i].size.width -= width;
3179 r[i].origin.x += width;
3183 /* Draw overlining, etc. on the cursor. */
3184 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3185 ns_draw_text_decoration (s, face, bgCol, width, x);
3187 ns_draw_text_decoration (s, face, fgCol, width, x);
3194 /* Draw overlining, etc. on the stretch glyph (or the part
3195 of the stretch glyph after the cursor). */
3196 ns_draw_text_decoration (s, face, fgCol, r[i].size.width,
3200 s->background_filled_p = 1;
3206 ns_draw_glyph_string (struct glyph_string *s)
3207 /* --------------------------------------------------------------------------
3208 External (RIF): Main draw-text call.
3209 -------------------------------------------------------------------------- */
3211 /* TODO (optimize): focus for box and contents draw */
3214 char box_drawn_p = 0;
3216 NSTRACE (ns_draw_glyph_string);
3218 if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
3221 struct glyph_string *next;
3223 for (width = 0, next = s->next;
3224 next && width < s->right_overhang;
3225 width += next->width, next = next->next)
3226 if (next->first_glyph->type != IMAGE_GLYPH)
3228 if (next->first_glyph->type != STRETCH_GLYPH)
3230 n = ns_get_glyph_string_clip_rect (s->next, r);
3231 ns_focus (s->f, r, n);
3232 ns_maybe_dumpglyphs_background (s->next, 1);
3237 ns_dumpglyphs_stretch (s->next);
3239 next->num_clips = 0;
3243 if (!s->for_overlaps && s->face->box != FACE_NO_BOX
3244 && (s->first_glyph->type == CHAR_GLYPH
3245 || s->first_glyph->type == COMPOSITE_GLYPH))
3247 n = ns_get_glyph_string_clip_rect (s, r);
3248 ns_focus (s->f, r, n);
3249 ns_maybe_dumpglyphs_background (s, 1);
3250 ns_dumpglyphs_box_or_relief (s);
3255 switch (s->first_glyph->type)
3259 n = ns_get_glyph_string_clip_rect (s, r);
3260 ns_focus (s->f, r, n);
3261 ns_dumpglyphs_image (s, r[0]);
3266 ns_dumpglyphs_stretch (s);
3270 case COMPOSITE_GLYPH:
3271 n = ns_get_glyph_string_clip_rect (s, r);
3272 ns_focus (s->f, r, n);
3274 if (s->for_overlaps || (s->cmp_from > 0
3275 && ! s->first_glyph->u.cmp.automatic))
3276 s->background_filled_p = 1;
3278 ns_maybe_dumpglyphs_background
3279 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3281 ns_tmp_flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
3282 (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
3283 (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
3284 NS_DUMPGLYPH_NORMAL));
3285 ns_tmp_font = (struct nsfont_info *)s->face->font;
3286 if (ns_tmp_font == NULL)
3287 ns_tmp_font = (struct nsfont_info *)FRAME_FONT (s->f);
3289 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3291 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3292 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3293 NS_FACE_FOREGROUND (s->face) = tmp;
3296 ns_tmp_font->font.driver->draw
3297 (s, 0, s->nchars, s->x, s->y,
3298 (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
3299 || ns_tmp_flags == NS_DUMPGLYPH_MOUSEFACE);
3301 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3303 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3304 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3305 NS_FACE_FOREGROUND (s->face) = tmp;
3311 case GLYPHLESS_GLYPH:
3312 n = ns_get_glyph_string_clip_rect (s, r);
3313 ns_focus (s->f, r, n);
3315 if (s->for_overlaps || (s->cmp_from > 0
3316 && ! s->first_glyph->u.cmp.automatic))
3317 s->background_filled_p = 1;
3319 ns_maybe_dumpglyphs_background
3320 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3322 /* Not yet implemented. */
3331 /* Draw box if not done already. */
3332 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
3334 n = ns_get_glyph_string_clip_rect (s, r);
3335 ns_focus (s->f, r, n);
3336 ns_dumpglyphs_box_or_relief (s);
3345 /* ==========================================================================
3349 ========================================================================== */
3353 ns_send_appdefined (int value)
3354 /* --------------------------------------------------------------------------
3355 Internal: post an appdefined event which EmacsApp-sendEvent will
3356 recognize and take as a command to halt the event loop.
3357 -------------------------------------------------------------------------- */
3359 /*NSTRACE (ns_send_appdefined); */
3361 /* Only post this event if we haven't already posted one. This will end
3362 the [NXApp run] main loop after having processed all events queued at
3364 if (send_appdefined)
3368 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
3369 send_appdefined = NO;
3371 /* Don't need wakeup timer any more */
3374 [timed_entry invalidate];
3375 [timed_entry release];
3379 nxev = [NSEvent otherEventWithType: NSApplicationDefined
3380 location: NSMakePoint (0, 0)
3383 windowNumber: [[NSApp mainWindow] windowNumber]
3384 context: [NSApp context]
3389 /* Post an application defined event on the event queue. When this is
3390 received the [NXApp run] will return, thus having processed all
3391 events which are currently queued. */
3392 [NSApp postEvent: nxev atStart: NO];
3396 #ifdef HAVE_NATIVE_FS
3400 Lisp_Object frame, tail;
3402 if (ns_last_use_native_fullscreen == ns_use_native_fullscreen)
3405 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
3407 /* Clear the mouse-moved flag for every frame on this display. */
3408 FOR_EACH_FRAME (tail, frame)
3410 struct frame *f = XFRAME (frame);
3413 EmacsView *view = FRAME_NS_VIEW (f);
3414 [view updateCollectionBehaviour];
3421 ns_get_pending_menu_title ()
3423 return menu_pending_title;
3426 /* Check if menu open should be cancelled or continued as normal. */
3428 ns_check_menu_open (NSMenu *menu)
3430 /* GNUStep and OSX <= 10.4 does not have cancelTracking. */
3431 #if defined(NS_IMPL_COCOA) && \
3432 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
3434 /* Click in menu bar? */
3435 NSArray *a = [[NSApp mainMenu] itemArray];
3438 for (i = 0; ! found && i < [a count]; i++)
3439 found = menu == [[a objectAtIndex:i] submenu];
3442 if (menu_will_open_state == MENU_NONE && emacs_event)
3444 NSEvent *theEvent = [NSApp currentEvent];
3445 struct frame *emacsframe = SELECTED_FRAME ();
3447 [menu cancelTracking];
3448 menu_will_open_state = MENU_PENDING;
3449 emacs_event->kind = MENU_BAR_ACTIVATE_EVENT;
3450 EV_TRAILER (theEvent);
3452 CGEventRef ourEvent = CGEventCreate (NULL);
3453 menu_mouse_point = CGEventGetLocation (ourEvent);
3454 CFRelease (ourEvent);
3455 xfree (menu_pending_title);
3456 menu_pending_title = xstrdup ([[menu title] UTF8String]);
3458 else if (menu_will_open_state == MENU_OPENING)
3460 menu_will_open_state = MENU_NONE;
3466 /* Redo saved menu click if state is MENU_PENDING. */
3468 ns_check_pending_open_menu ()
3470 #ifdef NS_IMPL_COCOA
3471 if (menu_will_open_state == MENU_PENDING)
3473 CGEventSourceRef source
3474 = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
3476 CGEventRef event = CGEventCreateMouseEvent (source,
3477 kCGEventLeftMouseDown,
3479 kCGMouseButtonLeft);
3480 CGEventSetType (event, kCGEventLeftMouseDown);
3481 CGEventPost (kCGHIDEventTap, event);
3485 menu_will_open_state = MENU_OPENING;
3492 ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3493 /* --------------------------------------------------------------------------
3494 External (hook): Post an event to ourself and keep reading events until
3495 we read it back again. In effect process all events which were waiting.
3496 From 21+ we have to manage the event buffer ourselves.
3497 -------------------------------------------------------------------------- */
3499 struct input_event ev;
3502 /* NSTRACE (ns_read_socket); */
3504 #ifdef HAVE_NATIVE_FS
3508 if ([NSApp modalWindow] != nil)
3511 if (hold_event_q.nr > 0)
3514 for (i = 0; i < hold_event_q.nr; ++i)
3515 kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit);
3516 hold_event_q.nr = 0;
3521 n_emacs_events_pending = 0;
3524 q_event_ptr = hold_quit;
3526 /* we manage autorelease pools by allocate/reallocate each time around
3527 the loop; strict nesting is occasionally violated but seems not to
3528 matter.. earlier methods using full nesting caused major memory leaks */
3529 [outerpool release];
3530 outerpool = [[NSAutoreleasePool alloc] init];
3532 /* If have pending open-file requests, attend to the next one of those. */
3533 if (ns_pending_files && [ns_pending_files count] != 0
3534 && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]])
3536 [ns_pending_files removeObjectAtIndex: 0];
3538 /* Deal with pending service requests. */
3539 else if (ns_pending_service_names && [ns_pending_service_names count] != 0
3541 NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
3542 withArg: [ns_pending_service_args objectAtIndex: 0]])
3544 [ns_pending_service_names removeObjectAtIndex: 0];
3545 [ns_pending_service_args removeObjectAtIndex: 0];
3549 /* Run and wait for events. We must always send one NX_APPDEFINED event
3550 to ourself, otherwise [NXApp run] will never exit. */
3551 send_appdefined = YES;
3552 ns_send_appdefined (-1);
3554 if (++apploopnr != 1)
3562 nevents = n_emacs_events_pending;
3563 n_emacs_events_pending = 0;
3564 emacs_event = q_event_ptr = NULL;
3572 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3573 fd_set *exceptfds, EMACS_TIME *timeout, sigset_t *sigmask)
3574 /* --------------------------------------------------------------------------
3575 Replacement for select, checking for events
3576 -------------------------------------------------------------------------- */
3580 struct input_event event;
3583 /* NSTRACE (ns_select); */
3585 #ifdef HAVE_NATIVE_FS
3589 if (hold_event_q.nr > 0)
3591 /* We already have events pending. */
3597 for (k = 0; k < nfds+1; k++)
3599 if (readfds && FD_ISSET(k, readfds)) ++nr;
3600 if (writefds && FD_ISSET(k, writefds)) ++nr;
3604 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
3605 return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
3607 [outerpool release];
3608 outerpool = [[NSAutoreleasePool alloc] init];
3611 send_appdefined = YES;
3614 pthread_mutex_lock (&select_mutex);
3619 select_readfds = *readfds;
3620 select_valid += SELECT_HAVE_READ;
3624 select_writefds = *writefds;
3625 select_valid += SELECT_HAVE_WRITE;
3630 select_timeout = *timeout;
3631 select_valid += SELECT_HAVE_TMO;
3634 pthread_mutex_unlock (&select_mutex);
3636 /* Inform fd_handler that select should be called */
3638 emacs_write (selfds[1], &c, 1);
3640 else if (nr == 0 && timeout)
3642 /* No file descriptor, just a timeout, no need to wake fd_handler */
3643 double time = EMACS_TIME_TO_DOUBLE (*timeout);
3644 timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
3647 @selector (timeout_handler:)
3652 else /* No timeout and no file descriptors, can this happen? */
3654 /* Send appdefined so we exit from the loop */
3655 ns_send_appdefined (-1);
3660 emacs_event = &event;
3661 if (++apploopnr != 1)
3668 if (nr > 0 && readfds)
3671 emacs_write (selfds[1], &c, 1);
3675 t = last_appdefined_event_data;
3677 if (t != NO_APPDEFINED_DATA)
3679 last_appdefined_event_data = NO_APPDEFINED_DATA;
3683 /* The NX_APPDEFINED event we received was a timeout. */
3688 /* The NX_APPDEFINED event we received was the result of
3689 at least one real input event arriving. */
3695 /* Received back from select () in fd_handler; copy the results */
3696 pthread_mutex_lock (&select_mutex);
3697 if (readfds) *readfds = select_readfds;
3698 if (writefds) *writefds = select_writefds;
3699 if (timeout) *timeout = select_timeout;
3700 pthread_mutex_unlock (&select_mutex);
3715 /* ==========================================================================
3719 ========================================================================== */
3723 ns_set_vertical_scroll_bar (struct window *window,
3724 int portion, int whole, int position)
3725 /* --------------------------------------------------------------------------
3726 External (hook): Update or add scrollbar
3727 -------------------------------------------------------------------------- */
3731 struct frame *f = XFRAME (WINDOW_FRAME (window));
3732 EmacsView *view = FRAME_NS_VIEW (f);
3733 int window_y, window_height;
3734 int top, left, height, width, sb_width, sb_left;
3736 BOOL fringe_extended_p;
3738 /* optimization; display engine sends WAY too many of these.. */
3739 if (!NILP (window->vertical_scroll_bar))
3741 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3742 if ([bar checkSamePosition: position portion: portion whole: whole])
3744 if (view->scrollbarsNeedingUpdate == 0)
3746 if (!windows_or_buffers_changed)
3750 view->scrollbarsNeedingUpdate--;
3754 NSTRACE (ns_set_vertical_scroll_bar);
3756 /* Get dimensions. */
3757 window_box (window, -1, 0, &window_y, 0, &window_height);
3759 height = window_height;
3760 width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
3761 left = WINDOW_SCROLL_BAR_AREA_X (window);
3763 /* allow for displaying a skinnier scrollbar than char area allotted */
3764 sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ?
3765 WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width;
3768 r = NSMakeRect (sb_left, top, sb_width, height);
3769 /* the parent view is flipped, so we need to flip y value */
3771 r.origin.y = (v.size.height - r.size.height - r.origin.y);
3773 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (window))
3774 fringe_extended_p = (WINDOW_LEFTMOST_P (window)
3775 && WINDOW_LEFT_FRINGE_WIDTH (window)
3776 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (window)
3777 || WINDOW_LEFT_MARGIN_COLS (window) == 0));
3779 fringe_extended_p = (WINDOW_RIGHTMOST_P (window)
3780 && WINDOW_RIGHT_FRINGE_WIDTH (window)
3781 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (window)
3782 || WINDOW_RIGHT_MARGIN_COLS (window) == 0));
3784 XSETWINDOW (win, window);
3787 /* we want at least 5 lines to display a scrollbar */
3788 if (WINDOW_TOTAL_LINES (window) < 5)
3790 if (!NILP (window->vertical_scroll_bar))
3792 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3793 [bar removeFromSuperview];
3794 wset_vertical_scroll_bar (window, Qnil);
3796 ns_clear_frame_area (f, sb_left, top, width, height);
3801 if (NILP (window->vertical_scroll_bar))
3803 if (width > 0 && height > 0)
3805 if (fringe_extended_p)
3806 ns_clear_frame_area (f, sb_left, top, sb_width, height);
3808 ns_clear_frame_area (f, left, top, width, height);
3811 bar = [[EmacsScroller alloc] initFrame: r window: win];
3812 wset_vertical_scroll_bar (window, make_save_pointer (bar));
3817 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3818 oldRect = [bar frame];
3819 r.size.width = oldRect.size.width;
3820 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
3822 if (oldRect.origin.x != r.origin.x)
3823 ns_clear_frame_area (f, sb_left, top, width, height);
3828 [bar setPosition: position portion: portion whole: whole];
3834 ns_condemn_scroll_bars (struct frame *f)
3835 /* --------------------------------------------------------------------------
3836 External (hook): arrange for all frame's scrollbars to be removed
3837 at next call to judge_scroll_bars, except for those redeemed.
3838 -------------------------------------------------------------------------- */
3842 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
3844 NSTRACE (ns_condemn_scroll_bars);
3846 for (i =[subviews count]-1; i >= 0; i--)
3848 view = [subviews objectAtIndex: i];
3849 if ([view isKindOfClass: [EmacsScroller class]])
3856 ns_redeem_scroll_bar (struct window *window)
3857 /* --------------------------------------------------------------------------
3858 External (hook): arrange to spare this window's scrollbar
3859 at next call to judge_scroll_bars.
3860 -------------------------------------------------------------------------- */
3863 NSTRACE (ns_redeem_scroll_bar);
3864 if (!NILP (window->vertical_scroll_bar))
3866 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3873 ns_judge_scroll_bars (struct frame *f)
3874 /* --------------------------------------------------------------------------
3875 External (hook): destroy all scrollbars on frame that weren't
3876 redeemed after call to condemn_scroll_bars.
3877 -------------------------------------------------------------------------- */
3881 EmacsView *eview = FRAME_NS_VIEW (f);
3882 NSArray *subviews = [[eview superview] subviews];
3885 NSTRACE (ns_judge_scroll_bars);
3886 for (i = [subviews count]-1; i >= 0; --i)
3888 view = [subviews objectAtIndex: i];
3889 if (![view isKindOfClass: [EmacsScroller class]]) continue;
3895 [eview updateFrameSize: NO];
3900 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
3902 /* XXX irrelevant under NS */
3907 /* ==========================================================================
3911 ========================================================================== */
3914 x_display_pixel_height (struct ns_display_info *dpyinfo)
3916 NSArray *screens = [NSScreen screens];
3917 NSEnumerator *enumerator = [screens objectEnumerator];
3922 while ((screen = [enumerator nextObject]) != nil)
3923 frame = NSUnionRect (frame, [screen frame]);
3925 return NSHeight (frame);
3929 x_display_pixel_width (struct ns_display_info *dpyinfo)
3931 NSArray *screens = [NSScreen screens];
3932 NSEnumerator *enumerator = [screens objectEnumerator];
3937 while ((screen = [enumerator nextObject]) != nil)
3938 frame = NSUnionRect (frame, [screen frame]);
3940 return NSWidth (frame);
3944 static Lisp_Object ns_string_to_lispmod (const char *s)
3945 /* --------------------------------------------------------------------------
3946 Convert modifier name to lisp symbol
3947 -------------------------------------------------------------------------- */
3949 if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10))
3951 else if (!strncmp (SSDATA (SYMBOL_NAME (Qsuper)), s, 10))
3953 else if (!strncmp (SSDATA (SYMBOL_NAME (Qcontrol)), s, 10))
3955 else if (!strncmp (SSDATA (SYMBOL_NAME (Qalt)), s, 10))
3957 else if (!strncmp (SSDATA (SYMBOL_NAME (Qhyper)), s, 10))
3959 else if (!strncmp (SSDATA (SYMBOL_NAME (Qnone)), s, 10))
3967 ns_default (const char *parameter, Lisp_Object *result,
3968 Lisp_Object yesval, Lisp_Object noval,
3969 BOOL is_float, BOOL is_modstring)
3970 /* --------------------------------------------------------------------------
3971 Check a parameter value in user's preferences
3972 -------------------------------------------------------------------------- */
3974 const char *value = ns_get_defaults_value (parameter);
3980 if (c_strcasecmp (value, "YES") == 0)
3982 else if (c_strcasecmp (value, "NO") == 0)
3984 else if (is_float && (f = strtod (value, &pos), pos != value))
3985 *result = make_float (f);
3986 else if (is_modstring && value)
3987 *result = ns_string_to_lispmod (value);
3988 else fprintf (stderr,
3989 "Bad value for default \"%s\": \"%s\"\n", parameter, value);
3995 ns_initialize_display_info (struct ns_display_info *dpyinfo)
3996 /* --------------------------------------------------------------------------
3997 Initialize global info and storage for display.
3998 -------------------------------------------------------------------------- */
4000 NSScreen *screen = [NSScreen mainScreen];
4001 NSWindowDepth depth = [screen depth];
4002 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
4004 dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
4005 dpyinfo->resy = 72.27;
4006 dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
4007 NSColorSpaceFromDepth (depth)]
4008 && ![NSCalibratedWhiteColorSpace isEqualToString:
4009 NSColorSpaceFromDepth (depth)];
4010 dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
4011 dpyinfo->image_cache = make_image_cache ();
4012 dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table);
4013 dpyinfo->color_table->colors = NULL;
4014 dpyinfo->root_window = 42; /* a placeholder.. */
4016 hlinfo->mouse_face_mouse_frame = NULL;
4017 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
4018 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
4019 hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
4020 hlinfo->mouse_face_window = hlinfo->mouse_face_overlay = Qnil;
4021 hlinfo->mouse_face_hidden = 0;
4023 hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0;
4024 hlinfo->mouse_face_defer = 0;
4026 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL;
4028 dpyinfo->n_fonts = 0;
4029 dpyinfo->smallest_font_height = 1;
4030 dpyinfo->smallest_char_width = 1;
4034 /* This and next define (many of the) public functions in this file. */
4035 /* x_... are generic versions in xdisp.c that we, and other terms, get away
4036 with using despite presence in the "system dependent" redisplay
4037 interface. In addition, many of the ns_ methods have code that is
4038 shared with all terms, indicating need for further refactoring. */
4039 extern frame_parm_handler ns_frame_parm_handlers[];
4040 static struct redisplay_interface ns_redisplay_interface =
4042 ns_frame_parm_handlers,
4046 x_clear_end_of_line,
4048 ns_after_update_window_line,
4049 ns_update_window_begin,
4050 ns_update_window_end,
4053 0, /* flush_display_optional */
4054 x_clear_window_mouse_face,
4055 x_get_glyph_overhangs,
4056 x_fix_overlapping_area,
4057 ns_draw_fringe_bitmap,
4058 0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
4059 0, /* destroy_fringe_bitmap */
4060 ns_compute_glyph_string_overhangs,
4061 ns_draw_glyph_string, /* interface to nsfont.m */
4062 ns_define_frame_cursor,
4063 ns_clear_frame_area,
4064 ns_draw_window_cursor,
4065 ns_draw_vertical_window_border,
4066 ns_shift_glyphs_for_insert
4071 ns_delete_display (struct ns_display_info *dpyinfo)
4077 /* This function is called when the last frame on a display is deleted. */
4079 ns_delete_terminal (struct terminal *terminal)
4081 struct ns_display_info *dpyinfo = terminal->display_info.ns;
4083 /* Protect against recursive calls. delete_frame in
4084 delete_terminal calls us back when it deletes our last frame. */
4085 if (!terminal->name)
4090 x_destroy_all_bitmaps (dpyinfo);
4091 ns_delete_display (dpyinfo);
4096 static struct terminal *
4097 ns_create_terminal (struct ns_display_info *dpyinfo)
4098 /* --------------------------------------------------------------------------
4099 Set up use of NS before we make the first connection.
4100 -------------------------------------------------------------------------- */
4102 struct terminal *terminal;
4104 NSTRACE (ns_create_terminal);
4106 terminal = create_terminal ();
4108 terminal->type = output_ns;
4109 terminal->display_info.ns = dpyinfo;
4110 dpyinfo->terminal = terminal;
4112 terminal->rif = &ns_redisplay_interface;
4114 terminal->clear_frame_hook = ns_clear_frame;
4115 terminal->ins_del_lines_hook = 0; /* XXX vestigial? */
4116 terminal->delete_glyphs_hook = 0; /* XXX vestigial? */
4117 terminal->ring_bell_hook = ns_ring_bell;
4118 terminal->reset_terminal_modes_hook = ns_reset_terminal_modes;
4119 terminal->set_terminal_modes_hook = ns_set_terminal_modes;
4120 terminal->update_begin_hook = ns_update_begin;
4121 terminal->update_end_hook = ns_update_end;
4122 terminal->set_terminal_window_hook = NULL; /* XXX vestigial? */
4123 terminal->read_socket_hook = ns_read_socket;
4124 terminal->frame_up_to_date_hook = ns_frame_up_to_date;
4125 terminal->mouse_position_hook = ns_mouse_position;
4126 terminal->frame_rehighlight_hook = ns_frame_rehighlight;
4127 terminal->frame_raise_lower_hook = ns_frame_raise_lower;
4129 terminal->fullscreen_hook = ns_fullscreen_hook;
4131 terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
4132 terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
4133 terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
4134 terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
4136 terminal->delete_frame_hook = x_destroy_window;
4137 terminal->delete_terminal_hook = ns_delete_terminal;
4139 terminal->scroll_region_ok = 1;
4140 terminal->char_ins_del_ok = 1;
4141 terminal->line_ins_del_ok = 1;
4142 terminal->fast_clear_end_of_line = 1;
4143 terminal->memory_below_frame = 0;
4149 struct ns_display_info *
4150 ns_term_init (Lisp_Object display_name)
4151 /* --------------------------------------------------------------------------
4152 Start the Application and get things rolling.
4153 -------------------------------------------------------------------------- */
4155 struct terminal *terminal;
4156 struct ns_display_info *dpyinfo;
4157 static int ns_initialized = 0;
4160 if (ns_initialized) return x_display_list;
4163 NSTRACE (ns_term_init);
4165 [outerpool release];
4166 outerpool = [[NSAutoreleasePool alloc] init];
4168 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
4169 /*GSDebugAllocationActive (YES); */
4173 Fset_input_interrupt_mode (Qnil);
4175 if (selfds[0] == -1)
4177 if (pipe (selfds) == -1)
4179 fprintf (stderr, "Failed to create pipe: %s\n",
4180 emacs_strerror (errno));
4184 fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
4185 FD_ZERO (&select_readfds);
4186 FD_ZERO (&select_writefds);
4187 pthread_mutex_init (&select_mutex, NULL);
4190 ns_pending_files = [[NSMutableArray alloc] init];
4191 ns_pending_service_names = [[NSMutableArray alloc] init];
4192 ns_pending_service_args = [[NSMutableArray alloc] init];
4194 /* Start app and create the main menu, window, view.
4195 Needs to be here because ns_initialize_display_info () uses AppKit classes.
4196 The view will then ask the NSApp to stop and return to Emacs. */
4197 [EmacsApp sharedApplication];
4200 [NSApp setDelegate: NSApp];
4202 /* Start the select thread. */
4203 [NSThread detachNewThreadSelector:@selector (fd_handler:)
4207 /* debugging: log all notifications */
4208 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
4209 selector: @selector (logNotification:)
4210 name: nil object: nil]; */
4212 dpyinfo = xzalloc (sizeof *dpyinfo);
4214 ns_initialize_display_info (dpyinfo);
4215 terminal = ns_create_terminal (dpyinfo);
4217 terminal->kboard = xmalloc (sizeof *terminal->kboard);
4218 init_kboard (terminal->kboard);
4219 kset_window_system (terminal->kboard, Qns);
4220 terminal->kboard->next_kboard = all_kboards;
4221 all_kboards = terminal->kboard;
4222 /* Don't let the initial kboard remain current longer than necessary.
4223 That would cause problems if a file loaded on startup tries to
4224 prompt in the mini-buffer. */
4225 if (current_kboard == initial_kboard)
4226 current_kboard = terminal->kboard;
4227 terminal->kboard->reference_count++;
4229 dpyinfo->next = x_display_list;
4230 x_display_list = dpyinfo;
4232 /* Put it on ns_display_name_list */
4233 ns_display_name_list = Fcons (Fcons (display_name, Qnil),
4234 ns_display_name_list);
4235 dpyinfo->name_list_element = XCAR (ns_display_name_list);
4237 terminal->name = xstrdup (SSDATA (display_name));
4241 if (!inhibit_x_resources)
4243 ns_default ("GSFontAntiAlias", &ns_antialias_text,
4246 /* this is a standard variable */
4247 ns_default ("AppleAntiAliasingThreshold", &tmp,
4248 make_float (10.0), make_float (6.0), YES, NO);
4249 ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
4252 ns_selection_color = [[NSUserDefaults standardUserDefaults]
4253 stringForKey: @"AppleHighlightColor"];
4254 if (ns_selection_color == nil)
4255 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
4258 NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
4262 Lisp_Object color_file, color_map, color;
4266 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4267 Fsymbol_value (intern ("data-directory")));
4269 color_map = Fx_load_color_file (color_file);
4270 if (NILP (color_map))
4271 fatal ("Could not read %s.\n", SDATA (color_file));
4273 cl = [[NSColorList alloc] initWithName: @"Emacs"];
4274 for ( ; CONSP (color_map); color_map = XCDR (color_map))
4276 color = XCAR (color_map);
4277 name = SSDATA (XCAR (color));
4278 c = XINT (XCDR (color));
4280 [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0
4281 green: GREEN_FROM_ULONG (c) / 255.0
4282 blue: BLUE_FROM_ULONG (c) / 255.0
4284 forKey: [NSString stringWithUTF8String: name]];
4286 [cl writeToFile: nil];
4291 #ifdef NS_IMPL_GNUSTEP
4292 Vwindow_system_version = build_string (gnustep_base_version);
4294 /*PSnextrelease (128, c); */
4295 char c[DBL_BUFSIZE_BOUND];
4296 int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber);
4297 Vwindow_system_version = make_unibyte_string (c, len);
4301 delete_keyboard_wait_descriptor (0);
4303 ns_app_name = [[NSProcessInfo processInfo] processName];
4305 /* Set up OS X app menu */
4306 #ifdef NS_IMPL_COCOA
4310 /* set up the application menu */
4311 svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
4312 [svcsMenu setAutoenablesItems: NO];
4313 appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
4314 [appMenu setAutoenablesItems: NO];
4315 mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
4316 dockMenu = [[EmacsMenu alloc] initWithTitle: @""];
4318 [appMenu insertItemWithTitle: @"About Emacs"
4319 action: @selector (orderFrontStandardAboutPanel:)
4322 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
4323 [appMenu insertItemWithTitle: @"Preferences..."
4324 action: @selector (showPreferencesWindow:)
4327 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
4328 item = [appMenu insertItemWithTitle: @"Services"
4329 action: @selector (menuDown:)
4332 [appMenu setSubmenu: svcsMenu forItem: item];
4333 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];
4334 [appMenu insertItemWithTitle: @"Hide Emacs"
4335 action: @selector (hide:)
4338 item = [appMenu insertItemWithTitle: @"Hide Others"
4339 action: @selector (hideOtherApplications:)
4342 [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
4343 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8];
4344 [appMenu insertItemWithTitle: @"Quit Emacs"
4345 action: @selector (terminate:)
4349 item = [mainMenu insertItemWithTitle: ns_app_name
4350 action: @selector (menuDown:)
4353 [mainMenu setSubmenu: appMenu forItem: item];
4354 [dockMenu insertItemWithTitle: @"New Frame"
4355 action: @selector (newFrame:)
4359 [NSApp setMainMenu: mainMenu];
4360 [NSApp setAppleMenu: appMenu];
4361 [NSApp setServicesMenu: svcsMenu];
4362 /* Needed at least on Cocoa, to get dock menu to show windows */
4363 [NSApp setWindowsMenu: [[NSMenu alloc] init]];
4365 [[NSNotificationCenter defaultCenter]
4366 addObserver: mainMenu
4367 selector: @selector (trackingNotification:)
4368 name: NSMenuDidBeginTrackingNotification object: mainMenu];
4369 [[NSNotificationCenter defaultCenter]
4370 addObserver: mainMenu
4371 selector: @selector (trackingNotification:)
4372 name: NSMenuDidEndTrackingNotification object: mainMenu];
4374 #endif /* MAC OS X menu setup */
4376 /* Register our external input/output types, used for determining
4377 applicable services and also drag/drop eligibility. */
4378 ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
4379 ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
4381 ns_drag_types = [[NSArray arrayWithObjects:
4383 NSTabularTextPboardType,
4384 NSFilenamesPboardType,
4387 NSFontPboardType, nil] retain];
4389 /* If fullscreen is in init/default-frame-alist, focus isn't set
4390 right for fullscreen windows, so set this. */
4391 [NSApp activateIgnoringOtherApps:YES];
4394 ns_do_open_file = YES;
4400 ns_term_shutdown (int sig)
4402 [[NSUserDefaults standardUserDefaults] synchronize];
4404 /* code not reached in emacs.c after this is called by shut_down_emacs: */
4405 if (STRINGP (Vauto_save_list_file_name))
4406 unlink (SSDATA (Vauto_save_list_file_name));
4408 if (sig == 0 || sig == SIGTERM)
4410 [NSApp terminate: NSApp];
4412 else // force a stack trace to happen
4419 /* ==========================================================================
4421 EmacsApp implementation
4423 ========================================================================== */
4426 @implementation EmacsApp
4428 - (void)logNotification: (NSNotification *)notification
4430 const char *name = [[notification name] UTF8String];
4431 if (!strstr (name, "Update") && !strstr (name, "NSMenu")
4432 && !strstr (name, "WindowNumber"))
4433 NSLog (@"notification: '%@'", [notification name]);
4437 - (void)sendEvent: (NSEvent *)theEvent
4438 /* --------------------------------------------------------------------------
4439 Called when NSApp is running for each event received. Used to stop
4440 the loop when we choose, since there's no way to just run one iteration.
4441 -------------------------------------------------------------------------- */
4443 int type = [theEvent type];
4444 NSWindow *window = [theEvent window];
4445 /* NSTRACE (sendEvent); */
4446 /*fprintf (stderr, "received event of type %d\t%d\n", type);*/
4448 #ifdef NS_IMPL_COCOA
4449 if (type == NSApplicationDefined
4450 && [theEvent data2] == NSAPP_DATA2_RUNASSCRIPT)
4458 if (type == NSCursorUpdate && window == nil)
4460 fprintf (stderr, "Dropping external cursor update event.\n");
4464 if (type == NSApplicationDefined)
4466 /* Events posted by ns_send_appdefined interrupt the run loop here.
4467 But, if a modal window is up, an appdefined can still come through,
4468 (e.g., from a makeKeyWindow event) but stopping self also stops the
4469 modal loop. Just defer it until later. */
4470 if ([NSApp modalWindow] == nil)
4472 last_appdefined_event_data = [theEvent data1];
4477 send_appdefined = YES;
4481 [super sendEvent: theEvent];
4485 - (void)showPreferencesWindow: (id)sender
4487 struct frame *emacsframe = SELECTED_FRAME ();
4488 NSEvent *theEvent = [NSApp currentEvent];
4492 emacs_event->kind = NS_NONKEY_EVENT;
4493 emacs_event->code = KEY_NS_SHOW_PREFS;
4494 emacs_event->modifiers = 0;
4495 EV_TRAILER (theEvent);
4499 - (void)newFrame: (id)sender
4501 struct frame *emacsframe = SELECTED_FRAME ();
4502 NSEvent *theEvent = [NSApp currentEvent];
4506 emacs_event->kind = NS_NONKEY_EVENT;
4507 emacs_event->code = KEY_NS_NEW_FRAME;
4508 emacs_event->modifiers = 0;
4509 EV_TRAILER (theEvent);
4513 /* Open a file (used by below, after going into queue read by ns_read_socket) */
4514 - (BOOL) openFile: (NSString *)fileName
4516 struct frame *emacsframe = SELECTED_FRAME ();
4517 NSEvent *theEvent = [NSApp currentEvent];
4522 emacs_event->kind = NS_NONKEY_EVENT;
4523 emacs_event->code = KEY_NS_OPEN_FILE_LINE;
4524 ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
4525 ns_input_line = Qnil; /* can be start or cons start,end */
4526 emacs_event->modifiers =0;
4527 EV_TRAILER (theEvent);
4533 /* **************************************************************************
4535 EmacsApp delegate implementation
4537 ************************************************************************** */
4539 - (void)applicationDidFinishLaunching: (NSNotification *)notification
4540 /* --------------------------------------------------------------------------
4541 When application is loaded, terminate event loop in ns_term_init
4542 -------------------------------------------------------------------------- */
4544 NSTRACE (applicationDidFinishLaunching);
4545 [NSApp setServicesProvider: NSApp];
4546 ns_send_appdefined (-2);
4550 /* Termination sequences:
4553 MenuBar | File | Exit:
4554 Select Quit from App menubar:
4556 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
4559 Select Quit from Dock menu:
4562 Cancel -> Nothing else
4566 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
4571 - (void) terminate: (id)sender
4573 struct frame *emacsframe = SELECTED_FRAME ();
4578 emacs_event->kind = NS_NONKEY_EVENT;
4579 emacs_event->code = KEY_NS_POWER_OFF;
4580 emacs_event->arg = Qt; /* mark as non-key event */
4581 EV_TRAILER ((id)nil);
4585 - (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
4589 if (NILP (ns_confirm_quit)) // || ns_shutdown_properly --> TO DO
4590 return NSTerminateNow;
4592 ret = NSRunAlertPanel(ns_app_name,
4593 @"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?",
4594 @"Save Buffers and Exit", @"Cancel", nil);
4596 if (ret == NSAlertDefaultReturn)
4597 return NSTerminateNow;
4598 else if (ret == NSAlertAlternateReturn)
4599 return NSTerminateCancel;
4600 return NSTerminateNow; /* just in case */
4604 not_in_argv (NSString *arg)
4607 const char *a = [arg UTF8String];
4608 for (k = 1; k < initial_argc; ++k)
4609 if (strcmp (a, initial_argv[k]) == 0) return 0;
4613 /* Notification from the Workspace to open a file */
4614 - (BOOL)application: sender openFile: (NSString *)file
4616 if (ns_do_open_file || not_in_argv (file))
4617 [ns_pending_files addObject: file];
4622 /* Open a file as a temporary file */
4623 - (BOOL)application: sender openTempFile: (NSString *)file
4625 if (ns_do_open_file || not_in_argv (file))
4626 [ns_pending_files addObject: file];
4631 /* Notification from the Workspace to open a file noninteractively (?) */
4632 - (BOOL)application: sender openFileWithoutUI: (NSString *)file
4634 if (ns_do_open_file || not_in_argv (file))
4635 [ns_pending_files addObject: file];
4639 /* Notification from the Workspace to open multiple files */
4640 - (void)application: sender openFiles: (NSArray *)fileList
4642 NSEnumerator *files = [fileList objectEnumerator];
4644 /* Don't open files from the command line unconditionally,
4645 Cocoa parses the command line wrong, --option value tries to open value
4646 if --option is the last option. */
4647 while ((file = [files nextObject]) != nil)
4648 if (ns_do_open_file || not_in_argv (file))
4649 [ns_pending_files addObject: file];
4651 [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
4656 /* Handle dock menu requests. */
4657 - (NSMenu *)applicationDockMenu: (NSApplication *) sender
4663 /* TODO: these may help w/IO switching btwn terminal and NSApp */
4664 - (void)applicationWillBecomeActive: (NSNotification *)notification
4666 //ns_app_active=YES;
4668 - (void)applicationDidBecomeActive: (NSNotification *)notification
4670 NSTRACE (applicationDidBecomeActive);
4672 //ns_app_active=YES;
4674 ns_update_auto_hide_menu_bar ();
4675 // No constraining takes place when the application is not active.
4676 ns_constrain_all_frames ();
4678 - (void)applicationDidResignActive: (NSNotification *)notification
4681 ns_send_appdefined (-1);
4686 /* ==========================================================================
4688 EmacsApp aux handlers for managing event loop
4690 ========================================================================== */
4693 - (void)timeout_handler: (NSTimer *)timedEntry
4694 /* --------------------------------------------------------------------------
4695 The timeout specified to ns_select has passed.
4696 -------------------------------------------------------------------------- */
4698 /*NSTRACE (timeout_handler); */
4699 ns_send_appdefined (-2);
4702 - (void)fd_handler:(id)unused
4703 /* --------------------------------------------------------------------------
4704 Check data waiting on file descriptors and terminate if so
4705 -------------------------------------------------------------------------- */
4708 int waiting = 1, nfds;
4711 SELECT_TYPE readfds, writefds, *wfds;
4712 EMACS_TIME timeout, *tmo;
4713 NSAutoreleasePool *pool = nil;
4715 /* NSTRACE (fd_handler); */
4720 pool = [[NSAutoreleasePool alloc] init];
4726 FD_SET (selfds[0], &fds);
4727 result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
4728 if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
4733 pthread_mutex_lock (&select_mutex);
4736 if (select_valid & SELECT_HAVE_READ)
4737 readfds = select_readfds;
4741 if (select_valid & SELECT_HAVE_WRITE)
4743 writefds = select_writefds;
4748 if (select_valid & SELECT_HAVE_TMO)
4750 timeout = select_timeout;
4756 pthread_mutex_unlock (&select_mutex);
4758 FD_SET (selfds[0], &readfds);
4759 if (selfds[0] >= nfds) nfds = selfds[0]+1;
4761 result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL);
4764 ns_send_appdefined (-2);
4765 else if (result > 0)
4767 if (FD_ISSET (selfds[0], &readfds))
4769 if (read (selfds[0], &c, 1) == 1 && c == 's')
4774 pthread_mutex_lock (&select_mutex);
4775 if (select_valid & SELECT_HAVE_READ)
4776 select_readfds = readfds;
4777 if (select_valid & SELECT_HAVE_WRITE)
4778 select_writefds = writefds;
4779 if (select_valid & SELECT_HAVE_TMO)
4780 select_timeout = timeout;
4781 pthread_mutex_unlock (&select_mutex);
4783 ns_send_appdefined (result);
4793 /* ==========================================================================
4797 ========================================================================== */
4799 /* called from system: queue for next pass through event loop */
4800 - (void)requestService: (NSPasteboard *)pboard
4801 userData: (NSString *)userData
4802 error: (NSString **)error
4804 [ns_pending_service_names addObject: userData];
4805 [ns_pending_service_args addObject: [NSString stringWithUTF8String:
4806 SSDATA (ns_string_from_pasteboard (pboard))]];
4810 /* called from ns_read_socket to clear queue */
4811 - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
4813 struct frame *emacsframe = SELECTED_FRAME ();
4814 NSEvent *theEvent = [NSApp currentEvent];
4819 emacs_event->kind = NS_NONKEY_EVENT;
4820 emacs_event->code = KEY_NS_SPI_SERVICE_CALL;
4821 ns_input_spi_name = build_string ([name UTF8String]);
4822 ns_input_spi_arg = build_string ([arg UTF8String]);
4823 emacs_event->modifiers = EV_MODIFIERS (theEvent);
4824 EV_TRAILER (theEvent);
4834 /* ==========================================================================
4836 EmacsView implementation
4838 ========================================================================== */
4841 @implementation EmacsView
4843 /* needed to inform when window closed from LISP */
4844 - (void) setWindowClosing: (BOOL)closing
4846 windowClosing = closing;
4852 NSTRACE (EmacsView_dealloc);
4854 if (fs_state == FULLSCREEN_BOTH)
4855 [nonfs_window release];
4860 /* called on font panel selection */
4861 - (void)changeFont: (id)sender
4863 NSEvent *e =[[self window] currentEvent];
4864 struct face *face =FRAME_DEFAULT_FACE (emacsframe);
4868 NSTRACE (changeFont);
4872 if ((newFont = [sender convertFont:
4873 ((struct nsfont_info *)face->font)->nsfont]))
4875 SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
4877 emacs_event->kind = NS_NONKEY_EVENT;
4878 emacs_event->modifiers = 0;
4879 emacs_event->code = KEY_NS_CHANGE_FONT;
4881 size = [newFont pointSize];
4882 ns_input_fontsize = make_number (lrint (size));
4883 ns_input_font = build_string ([[newFont familyName] UTF8String]);
4889 - (BOOL)acceptsFirstResponder
4891 NSTRACE (acceptsFirstResponder);
4896 - (void)resetCursorRects
4898 NSRect visible = [self visibleRect];
4899 NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
4900 NSTRACE (resetCursorRects);
4902 if (currentCursor == nil)
4903 currentCursor = [NSCursor arrowCursor];
4905 if (!NSIsEmptyRect (visible))
4906 [self addCursorRect: visible cursor: currentCursor];
4907 [currentCursor setOnMouseEntered: YES];
4912 /*****************************************************************************/
4913 /* Keyboard handling. */
4916 - (void)keyDown: (NSEvent *)theEvent
4918 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
4920 unsigned fnKeysym = 0;
4921 static NSMutableArray *nsEvArray;
4922 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
4923 static BOOL firstTime = YES;
4926 unsigned int flags = [theEvent modifierFlags];
4930 /* Rhapsody and OS X give up and down events for the arrow keys */
4931 if (ns_fake_keydown == YES)
4932 ns_fake_keydown = NO;
4933 else if ([theEvent type] != NSKeyDown)
4939 if (![[self window] isKeyWindow]
4940 && [[theEvent window] isKindOfClass: [EmacsWindow class]]
4941 /* we must avoid an infinite loop here. */
4942 && (EmacsView *)[[theEvent window] delegate] != self)
4944 /* XXX: There is an occasional condition in which, when Emacs display
4945 updates a different frame from the current one, and temporarily
4946 selects it, then processes some interrupt-driven input
4947 (dispnew.c:3878), OS will send the event to the correct NSWindow, but
4948 for some reason that window has its first responder set to the NSView
4949 most recently updated (I guess), which is not the correct one. */
4950 [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
4954 if (nsEvArray == nil)
4955 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
4957 [NSCursor setHiddenUntilMouseMoves: YES];
4959 if (hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
4961 clear_mouse_face (hlinfo);
4962 hlinfo->mouse_face_hidden = 1;
4965 if (!processingCompose)
4967 /* When using screen sharing, no left or right information is sent,
4968 so use Left key in those cases. */
4969 int is_left_key, is_right_key;
4971 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
4972 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
4974 /* (Carbon way: [theEvent keyCode]) */
4976 /* is it a "function key"? */
4977 fnKeysym = (code < 0x00ff && (flags&NSNumericPadKeyMask))
4978 ? ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask)
4979 : ns_convert_key (code);
4983 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
4984 because Emacs treats Delete and KP-Delete same (in simple.el). */
4985 if (fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33)
4986 code = 0xFF08; /* backspace */
4991 /* are there modifiers? */
4992 emacs_event->modifiers = 0;
4994 if (flags & NSHelpKeyMask)
4995 emacs_event->modifiers |= hyper_modifier;
4997 if (flags & NSShiftKeyMask)
4998 emacs_event->modifiers |= shift_modifier;
5000 is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask;
5001 is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
5002 || (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask);
5005 emacs_event->modifiers |= parse_solitary_modifier
5006 (EQ (ns_right_command_modifier, Qleft)
5007 ? ns_command_modifier
5008 : ns_right_command_modifier);
5012 emacs_event->modifiers |= parse_solitary_modifier
5013 (ns_command_modifier);
5015 /* if super (default), take input manager's word so things like
5016 dvorak / qwerty layout work */
5017 if (EQ (ns_command_modifier, Qsuper)
5019 && [[theEvent characters] length] != 0)
5021 /* XXX: the code we get will be unshifted, so if we have
5022 a shift modifier, must convert ourselves */
5023 if (!(flags & NSShiftKeyMask))
5024 code = [[theEvent characters] characterAtIndex: 0];
5026 /* this is ugly and also requires linking w/Carbon framework
5027 (for LMGetKbdType) so for now leave this rare (?) case
5028 undealt with.. in future look into CGEvent methods */
5031 long smv = GetScriptManagerVariable (smKeyScript);
5032 Handle uchrHandle = GetResource
5033 ('uchr', GetScriptVariable (smv, smScriptKeys));
5035 UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle,
5036 [[theEvent characters] characterAtIndex: 0],
5037 kUCKeyActionDisplay,
5038 (flags & ~NSCommandKeyMask) >> 8,
5039 LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask,
5040 &dummy, 1, &dummy, &code);
5047 is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask;
5048 is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask
5049 || (! is_right_key && (flags & NSControlKeyMask) == NSControlKeyMask);
5052 emacs_event->modifiers |= parse_solitary_modifier
5053 (EQ (ns_right_control_modifier, Qleft)
5054 ? ns_control_modifier
5055 : ns_right_control_modifier);
5058 emacs_event->modifiers |= parse_solitary_modifier
5059 (ns_control_modifier);
5061 if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
5062 emacs_event->modifiers |=
5063 parse_solitary_modifier (ns_function_modifier);
5065 left_is_none = NILP (ns_alternate_modifier)
5066 || EQ (ns_alternate_modifier, Qnone);
5068 is_right_key = (flags & NSRightAlternateKeyMask)
5069 == NSRightAlternateKeyMask;
5070 is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
5072 && (flags & NSAlternateKeyMask) == NSAlternateKeyMask);
5076 if ((NILP (ns_right_alternate_modifier)
5077 || EQ (ns_right_alternate_modifier, Qnone)
5078 || (EQ (ns_right_alternate_modifier, Qleft) && left_is_none))
5080 { /* accept pre-interp alt comb */
5081 if ([[theEvent characters] length] > 0)
5082 code = [[theEvent characters] characterAtIndex: 0];
5083 /*HACK: clear lone shift modifier to stop next if from firing */
5084 if (emacs_event->modifiers == shift_modifier)
5085 emacs_event->modifiers = 0;
5088 emacs_event->modifiers |= parse_solitary_modifier
5089 (EQ (ns_right_alternate_modifier, Qleft)
5090 ? ns_alternate_modifier
5091 : ns_right_alternate_modifier);
5094 if (is_left_key) /* default = meta */
5096 if (left_is_none && !fnKeysym)
5097 { /* accept pre-interp alt comb */
5098 if ([[theEvent characters] length] > 0)
5099 code = [[theEvent characters] characterAtIndex: 0];
5100 /*HACK: clear lone shift modifier to stop next if from firing */
5101 if (emacs_event->modifiers == shift_modifier)
5102 emacs_event->modifiers = 0;
5105 emacs_event->modifiers |=
5106 parse_solitary_modifier (ns_alternate_modifier);
5110 fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",
5111 code, fnKeysym, flags, emacs_event->modifiers);
5113 /* if it was a function key or had modifiers, pass it directly to emacs */
5114 if (fnKeysym || (emacs_event->modifiers
5115 && (emacs_event->modifiers != shift_modifier)
5116 && [[theEvent charactersIgnoringModifiers] length] > 0))
5117 /*[[theEvent characters] length] */
5119 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5121 code |= (1<<28)|(3<<16);
5122 else if (code == 0x7f)
5123 code |= (1<<28)|(3<<16);
5125 emacs_event->kind = code > 0xFF
5126 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5128 emacs_event->code = code;
5129 EV_TRAILER (theEvent);
5130 processingCompose = NO;
5136 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
5137 /* if we get here we should send the key for input manager processing */
5138 if (firstTime && [[NSInputManager currentInputManager]
5139 wantsToDelayTextChangeNotifications] == NO)
5141 "Emacs: WARNING: TextInput mgr wants marked text to be permanent!\n");
5144 if (NS_KEYLOG && !processingCompose)
5145 fprintf (stderr, "keyDown: Begin compose sequence.\n");
5147 processingCompose = YES;
5148 [nsEvArray addObject: theEvent];
5149 [self interpretKeyEvents: nsEvArray];
5150 [nsEvArray removeObject: theEvent];
5154 #ifdef NS_IMPL_COCOA
5155 /* Needed to pick up Ctrl-tab and possibly other events that OS X has
5156 decided not to send key-down for.
5157 See http://osdir.com/ml/editors.vim.mac/2007-10/msg00141.html
5158 This only applies on Tiger and earlier.
5159 If it matches one of these, send it on to keyDown. */
5160 -(void)keyUp: (NSEvent *)theEvent
5162 int flags = [theEvent modifierFlags];
5163 int code = [theEvent keyCode];
5164 if (floor (NSAppKitVersionNumber) <= 824 /*NSAppKitVersionNumber10_4*/ &&
5165 code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask))
5168 fprintf (stderr, "keyUp: passed test");
5169 ns_fake_keydown = YES;
5170 [self keyDown: theEvent];
5176 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
5179 /* <NSTextInput>: called when done composing;
5180 NOTE: also called when we delete over working text, followed immed.
5181 by doCommandBySelector: deleteBackward: */
5182 - (void)insertText: (id)aString
5185 int len = [(NSString *)aString length];
5189 NSLog (@"insertText '%@'\tlen = %d", aString, len);
5190 processingCompose = NO;
5195 /* first, clear any working text */
5196 if (workingText != nil)
5197 [self deleteWorkingText];
5199 /* now insert the string as keystrokes */
5200 for (i =0; i<len; i++)
5202 code = [aString characterAtIndex: i];
5203 /* TODO: still need this? */
5205 code = '~'; /* 0x7E */
5206 if (code != 32) /* Space */
5207 emacs_event->modifiers = 0;
5209 = code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5210 emacs_event->code = code;
5211 EV_TRAILER ((id)nil);
5216 /* <NSTextInput>: inserts display of composing characters */
5217 - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
5219 NSString *str = [aString respondsToSelector: @selector (string)] ?
5220 [aString string] : aString;
5222 NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
5223 selRange.length, selRange.location);
5225 if (workingText != nil)
5226 [self deleteWorkingText];
5227 if ([str length] == 0)
5233 processingCompose = YES;
5234 workingText = [str copy];
5235 ns_working_text = build_string ([workingText UTF8String]);
5237 emacs_event->kind = NS_TEXT_EVENT;
5238 emacs_event->code = KEY_NS_PUT_WORKING_TEXT;
5239 EV_TRAILER ((id)nil);
5243 /* delete display of composing characters [not in <NSTextInput>] */
5244 - (void)deleteWorkingText
5246 if (workingText == nil)
5249 NSLog(@"deleteWorkingText len =%d\n", [workingText length]);
5250 [workingText release];
5252 processingCompose = NO;
5257 emacs_event->kind = NS_TEXT_EVENT;
5258 emacs_event->code = KEY_NS_UNPUT_WORKING_TEXT;
5259 EV_TRAILER ((id)nil);
5263 - (BOOL)hasMarkedText
5265 return workingText != nil;
5269 - (NSRange)markedRange
5271 NSRange rng = workingText != nil
5272 ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
5274 NSLog (@"markedRange request");
5282 NSLog (@"unmark (accept) text");
5283 [self deleteWorkingText];
5284 processingCompose = NO;
5288 /* used to position char selection windows, etc. */
5289 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
5293 struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
5295 NSLog (@"firstRectForCharRange request");
5297 rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
5298 rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
5299 pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x);
5300 pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y
5301 +FRAME_LINE_HEIGHT (emacsframe));
5303 pt = [self convertPoint: pt toView: nil];
5304 pt = [[self window] convertBaseToScreen: pt];
5310 - (NSInteger)conversationIdentifier
5312 return (NSInteger)self;
5316 - (void)doCommandBySelector: (SEL)aSelector
5319 NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
5321 processingCompose = NO;
5322 if (aSelector == @selector (deleteBackward:))
5324 /* happens when user backspaces over an ongoing composition:
5325 throw a 'delete' into the event queue */
5328 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5329 emacs_event->code = 0xFF08;
5330 EV_TRAILER ((id)nil);
5334 - (NSArray *)validAttributesForMarkedText
5336 static NSArray *arr = nil;
5337 if (arr == nil) arr = [NSArray new];
5338 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
5342 - (NSRange)selectedRange
5345 NSLog (@"selectedRange request");
5346 return NSMakeRange (NSNotFound, 0);
5349 - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
5352 NSLog (@"characterIndexForPoint request");
5356 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
5358 static NSAttributedString *str = nil;
5359 if (str == nil) str = [NSAttributedString new];
5361 NSLog (@"attributedSubstringFromRange request");
5365 /* End <NSTextInput> impl. */
5366 /*****************************************************************************/
5369 /* This is what happens when the user presses a mouse button. */
5370 - (void)mouseDown: (NSEvent *)theEvent
5372 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
5374 NSTRACE (mouseDown);
5376 [self deleteWorkingText];
5381 last_mouse_frame = emacsframe;
5382 /* appears to be needed to prevent spurious movement events generated on
5384 last_mouse_frame->mouse_moved = 0;
5386 if ([theEvent type] == NSScrollWheel)
5388 float delta = [theEvent deltaY];
5389 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
5392 emacs_event->kind = WHEEL_EVENT;
5393 emacs_event->code = 0;
5394 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
5395 ((delta > 0) ? up_modifier : down_modifier);
5399 emacs_event->kind = MOUSE_CLICK_EVENT;
5400 emacs_event->code = EV_BUTTON (theEvent);
5401 emacs_event->modifiers = EV_MODIFIERS (theEvent)
5402 | EV_UDMODIFIERS (theEvent);
5404 XSETINT (emacs_event->x, lrint (p.x));
5405 XSETINT (emacs_event->y, lrint (p.y));
5406 EV_TRAILER (theEvent);
5410 - (void)rightMouseDown: (NSEvent *)theEvent
5412 NSTRACE (rightMouseDown);
5413 [self mouseDown: theEvent];
5417 - (void)otherMouseDown: (NSEvent *)theEvent
5419 NSTRACE (otherMouseDown);
5420 [self mouseDown: theEvent];
5424 - (void)mouseUp: (NSEvent *)theEvent
5427 [self mouseDown: theEvent];
5431 - (void)rightMouseUp: (NSEvent *)theEvent
5433 NSTRACE (rightMouseUp);
5434 [self mouseDown: theEvent];
5438 - (void)otherMouseUp: (NSEvent *)theEvent
5440 NSTRACE (otherMouseUp);
5441 [self mouseDown: theEvent];
5445 - (void) scrollWheel: (NSEvent *)theEvent
5447 NSTRACE (scrollWheel);
5448 [self mouseDown: theEvent];
5452 /* Tell emacs the mouse has moved. */
5453 - (void)mouseMoved: (NSEvent *)e
5455 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
5458 // NSTRACE (mouseMoved);
5460 last_mouse_movement_time = EV_TIMESTAMP (e);
5461 last_mouse_motion_position
5462 = [self convertPoint: [e locationInWindow] fromView: nil];
5464 /* update any mouse face */
5465 if (hlinfo->mouse_face_hidden)
5467 hlinfo->mouse_face_hidden = 0;
5468 clear_mouse_face (hlinfo);
5471 /* tooltip handling */
5472 previous_help_echo_string = help_echo_string;
5473 help_echo_string = Qnil;
5475 if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x,
5476 last_mouse_motion_position.y))
5477 help_echo_string = previous_help_echo_string;
5479 XSETFRAME (frame, emacsframe);
5480 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
5482 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
5483 (note_mouse_highlight), which is called through the
5484 note_mouse_movement () call above */
5485 gen_help_event (help_echo_string, frame, help_echo_window,
5486 help_echo_object, help_echo_pos);
5490 help_echo_string = Qnil;
5491 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
5494 if (emacsframe->mouse_moved && send_appdefined)
5495 ns_send_appdefined (-1);
5499 - (void)mouseDragged: (NSEvent *)e
5501 NSTRACE (mouseDragged);
5502 [self mouseMoved: e];
5506 - (void)rightMouseDragged: (NSEvent *)e
5508 NSTRACE (rightMouseDragged);
5509 [self mouseMoved: e];
5513 - (void)otherMouseDragged: (NSEvent *)e
5515 NSTRACE (otherMouseDragged);
5516 [self mouseMoved: e];
5520 - (BOOL)windowShouldClose: (id)sender
5522 NSEvent *e =[[self window] currentEvent];
5524 NSTRACE (windowShouldClose);
5525 windowClosing = YES;
5528 emacs_event->kind = DELETE_WINDOW_EVENT;
5529 emacs_event->modifiers = 0;
5530 emacs_event->code = 0;
5532 /* Don't close this window, let this be done from lisp code. */
5536 - (void) updateFrameSize: (BOOL) delay;
5538 NSWindow *window = [self window];
5539 NSRect wr = [window frame];
5542 #ifdef NS_IMPL_GNUSTEP
5546 int oldc = cols, oldr = rows;
5547 int oldw = FRAME_PIXEL_WIDTH (emacsframe),
5548 oldh = FRAME_PIXEL_HEIGHT (emacsframe);
5551 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + gsextra);
5553 if (cols < MINWIDTH)
5556 if (! [self isFullscreen])
5558 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5559 + FRAME_TOOLBAR_HEIGHT (emacsframe) - gsextra;
5562 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, wr.size.height - extra);
5564 if (rows < MINHEIGHT)
5567 neww = (int)wr.size.width - emacsframe->border_width;
5568 newh = (int)wr.size.height - extra;
5570 if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
5572 struct frame *f = emacsframe;
5573 NSView *view = FRAME_NS_VIEW (emacsframe);
5574 NSWindow *win = [view window];
5575 NSSize sz = [win resizeIncrements];
5577 FRAME_PIXEL_WIDTH (emacsframe) = neww;
5578 FRAME_PIXEL_HEIGHT (emacsframe) = newh;
5579 change_frame_size (emacsframe, rows, cols, 0, delay, 0);
5580 SET_FRAME_GARBAGED (emacsframe);
5581 cancel_mouse_face (emacsframe);
5583 // Did resize increments change because of a font change?
5584 if (sz.width != FRAME_COLUMN_WIDTH (emacsframe) ||
5585 sz.height != FRAME_LINE_HEIGHT (emacsframe))
5587 sz.width = FRAME_COLUMN_WIDTH (emacsframe);
5588 sz.height = FRAME_LINE_HEIGHT (emacsframe);
5589 [win setResizeIncrements: sz];
5592 [view setFrame: NSMakeRect (0, 0, neww, newh)];
5593 [self windowDidMove:nil]; // Update top/left.
5597 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
5598 /* normalize frame to gridded text size */
5602 #ifdef NS_IMPL_GNUSTEP
5606 NSTRACE (windowWillResize);
5607 /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
5609 if (fs_state == FULLSCREEN_MAXIMIZED
5610 && (maximized_width != (int)frameSize.width
5611 || maximized_height != (int)frameSize.height))
5612 [self setFSValue: FULLSCREEN_NONE];
5613 else if (fs_state == FULLSCREEN_WIDTH
5614 && maximized_width != (int)frameSize.width)
5615 [self setFSValue: FULLSCREEN_NONE];
5616 else if (fs_state == FULLSCREEN_HEIGHT
5617 && maximized_height != (int)frameSize.height)
5618 [self setFSValue: FULLSCREEN_NONE];
5619 if (fs_state == FULLSCREEN_NONE)
5620 maximized_width = maximized_height = -1;
5622 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
5623 frameSize.width + gsextra);
5624 if (cols < MINWIDTH)
5627 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe,
5628 frameSize.height - extra);
5629 if (rows < MINHEIGHT)
5631 #ifdef NS_IMPL_COCOA
5633 /* this sets window title to have size in it; the wm does this under GS */
5634 NSRect r = [[self window] frame];
5635 if (r.size.height == frameSize.height && r.size.width == frameSize.width)
5646 NSWindow *window = [self window];
5649 const char *t = [[[self window] title] UTF8String];
5650 char *pos = strstr (t, " — ");
5653 old_title = xstrdup (t);
5655 size_title = xmalloc (strlen (old_title) + 40);
5656 esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
5657 [window setTitle: [NSString stringWithUTF8String: size_title]];
5662 #endif /* NS_IMPL_COCOA */
5663 /*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */
5669 - (void)windowDidResize: (NSNotification *)notification
5671 if (! [self fsIsNative])
5673 NSWindow *theWindow = [notification object];
5674 /* We can get notification on the non-FS window when in
5676 if ([self window] != theWindow) return;
5679 #ifdef NS_IMPL_GNUSTEP
5680 NSWindow *theWindow = [notification object];
5682 /* In GNUstep, at least currently, it's possible to get a didResize
5683 without getting a willResize.. therefore we need to act as if we got
5684 the willResize now */
5685 NSSize sz = [theWindow frame].size;
5686 sz = [self windowWillResize: theWindow toSize: sz];
5687 #endif /* NS_IMPL_GNUSTEP */
5689 NSTRACE (windowDidResize);
5690 /*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */
5692 #ifdef NS_IMPL_COCOA
5698 #endif /* NS_IMPL_COCOA */
5700 if (cols > 0 && rows > 0)
5702 [self updateFrameSize: YES];
5705 ns_send_appdefined (-1);
5709 - (void)windowDidBecomeKey: (NSNotification *)notification
5710 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5712 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5713 struct frame *old_focus = dpyinfo->x_focus_frame;
5715 NSTRACE (windowDidBecomeKey);
5717 if (emacsframe != old_focus)
5718 dpyinfo->x_focus_frame = emacsframe;
5720 ns_frame_rehighlight (emacsframe);
5724 emacs_event->kind = FOCUS_IN_EVENT;
5725 EV_TRAILER ((id)nil);
5730 - (void)windowDidResignKey: (NSNotification *)notification
5731 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5733 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5734 NSTRACE (windowDidResignKey);
5736 if (dpyinfo->x_focus_frame == emacsframe)
5737 dpyinfo->x_focus_frame = 0;
5739 ns_frame_rehighlight (emacsframe);
5741 /* FIXME: for some reason needed on second and subsequent clicks away
5742 from sole-frame Emacs to get hollow box to show */
5743 if (!windowClosing && [[self window] isVisible] == YES)
5745 x_update_cursor (emacsframe, 1);
5746 x_set_frame_alpha (emacsframe);
5751 [self deleteWorkingText];
5752 emacs_event->kind = FOCUS_IN_EVENT;
5753 EV_TRAILER ((id)nil);
5758 - (void)windowWillMiniaturize: sender
5760 NSTRACE (windowWillMiniaturize);
5776 - initFrameFromEmacs: (struct frame *)f
5781 NSButton *toggleButton;
5786 NSTRACE (initFrameFromEmacs);
5789 processingCompose = NO;
5790 scrollbarsNeedingUpdate = 0;
5791 fs_state = FULLSCREEN_NONE;
5792 fs_before_fs = next_maximized = -1;
5793 #ifdef HAVE_NATIVE_FS
5794 fs_is_native = ns_use_native_fullscreen;
5798 maximized_width = maximized_height = -1;
5801 /*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
5803 ns_userRect = NSMakeRect (0, 0, 0, 0);
5804 r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
5805 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
5806 [self initWithFrame: r];
5807 [self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
5809 FRAME_NS_VIEW (f) = self;
5813 win = [[EmacsWindow alloc]
5814 initWithContentRect: r
5815 styleMask: (NSResizableWindowMask |
5816 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
5817 NSTitledWindowMask |
5819 NSMiniaturizableWindowMask |
5820 NSClosableWindowMask)
5821 backing: NSBackingStoreBuffered
5824 #ifdef HAVE_NATIVE_FS
5825 [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
5829 bwidth = f->border_width = wr.size.width - r.size.width;
5830 tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
5832 [win setAcceptsMouseMovedEvents: YES];
5833 [win setDelegate: self];
5834 [win useOptimizedDrawing: YES];
5836 sz.width = FRAME_COLUMN_WIDTH (f);
5837 sz.height = FRAME_LINE_HEIGHT (f);
5838 [win setResizeIncrements: sz];
5840 [[win contentView] addSubview: self];
5843 [self registerForDraggedTypes: ns_drag_types];
5846 name = [NSString stringWithUTF8String:
5847 NILP (tem) ? "Emacs" : SSDATA (tem)];
5848 [win setTitle: name];
5850 /* toolbar support */
5851 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
5852 [NSString stringWithFormat: @"Emacs Frame %d",
5854 [win setToolbar: toolbar];
5855 [toolbar setVisible: NO];
5856 #ifdef NS_IMPL_COCOA
5857 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
5858 [toggleButton setTarget: self];
5859 [toggleButton setAction: @selector (toggleToolbar: )];
5861 FRAME_TOOLBAR_HEIGHT (f) = 0;
5865 [win setMiniwindowTitle:
5866 [NSString stringWithUTF8String: SSDATA (tem)]];
5869 NSScreen *screen = [win screen];
5872 [win setFrameTopLeftPoint: NSMakePoint
5873 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
5874 IN_BOUND (-SCREENMAX,
5875 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX))];
5878 [win makeFirstResponder: self];
5880 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
5881 (FRAME_DEFAULT_FACE (emacsframe)), emacsframe);
5882 [win setBackgroundColor: col];
5883 if ([col alphaComponent] != 1.0)
5884 [win setOpaque: NO];
5886 [self allocateGState];
5888 [NSApp registerServicesMenuSendTypes: ns_send_types
5896 - (void)windowDidMove: sender
5898 NSWindow *win = [self window];
5899 NSRect r = [win frame];
5900 NSArray *screens = [NSScreen screens];
5901 NSScreen *screen = [screens objectAtIndex: 0];
5903 NSTRACE (windowDidMove);
5905 if (!emacsframe->output_data.ns)
5909 emacsframe->left_pos = r.origin.x;
5910 emacsframe->top_pos =
5911 [screen frame].size.height - (r.origin.y + r.size.height);
5916 /* Called AFTER method below, but before our windowWillResize call there leads
5917 to windowDidResize -> x_set_window_size. Update emacs' notion of frame
5918 location so set_window_size moves the frame. */
5919 - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
5921 emacsframe->output_data.ns->zooming = 1;
5926 /* Override to do something slightly nonstandard, but nice. First click on
5927 zoom button will zoom vertically. Second will zoom completely. Third
5928 returns to original. */
5929 - (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
5930 defaultFrame:(NSRect)defaultFrame
5932 NSRect result = [sender frame];
5934 NSTRACE (windowWillUseStandardFrame);
5936 if (fs_before_fs != -1) /* Entering fullscreen */
5938 result = defaultFrame;
5940 else if (next_maximized == FULLSCREEN_HEIGHT
5941 || (next_maximized == -1
5942 && abs (defaultFrame.size.height - result.size.height)
5943 > FRAME_LINE_HEIGHT (emacsframe)))
5946 ns_userRect = result;
5947 maximized_height = result.size.height = defaultFrame.size.height;
5948 maximized_width = -1;
5949 result.origin.y = defaultFrame.origin.y;
5950 [self setFSValue: FULLSCREEN_HEIGHT];
5952 else if (next_maximized == FULLSCREEN_WIDTH)
5954 ns_userRect = result;
5955 maximized_width = result.size.width = defaultFrame.size.width;
5956 maximized_height = -1;
5957 result.origin.x = defaultFrame.origin.x;
5958 [self setFSValue: FULLSCREEN_WIDTH];
5960 else if (next_maximized == FULLSCREEN_MAXIMIZED
5961 || (next_maximized == -1
5962 && abs (defaultFrame.size.width - result.size.width)
5963 > FRAME_COLUMN_WIDTH (emacsframe)))
5965 result = defaultFrame; /* second click */
5966 maximized_width = result.size.width;
5967 maximized_height = result.size.height;
5968 [self setFSValue: FULLSCREEN_MAXIMIZED];
5973 result = ns_userRect.size.height ? ns_userRect : result;
5974 ns_userRect = NSMakeRect (0, 0, 0, 0);
5975 [self setFSValue: FULLSCREEN_NONE];
5976 maximized_width = maximized_width = -1;
5979 if (fs_before_fs == -1) next_maximized = -1;
5980 [self windowWillResize: sender toSize: result.size];
5985 - (void)windowDidDeminiaturize: sender
5987 NSTRACE (windowDidDeminiaturize);
5988 if (!emacsframe->output_data.ns)
5991 SET_FRAME_ICONIFIED (emacsframe, 0);
5992 SET_FRAME_VISIBLE (emacsframe, 1);
5993 windows_or_buffers_changed++;
5997 emacs_event->kind = DEICONIFY_EVENT;
5998 EV_TRAILER ((id)nil);
6003 - (void)windowDidExpose: sender
6005 NSTRACE (windowDidExpose);
6006 if (!emacsframe->output_data.ns)
6009 SET_FRAME_VISIBLE (emacsframe, 1);
6010 SET_FRAME_GARBAGED (emacsframe);
6012 if (send_appdefined)
6013 ns_send_appdefined (-1);
6017 - (void)windowDidMiniaturize: sender
6019 NSTRACE (windowDidMiniaturize);
6020 if (!emacsframe->output_data.ns)
6023 SET_FRAME_ICONIFIED (emacsframe, 1);
6024 SET_FRAME_VISIBLE (emacsframe, 0);
6028 emacs_event->kind = ICONIFY_EVENT;
6029 EV_TRAILER ((id)nil);
6033 #ifdef HAVE_NATIVE_FS
6034 - (NSApplicationPresentationOptions)window:(NSWindow *)window
6035 willUseFullScreenPresentationOptions:
6036 (NSApplicationPresentationOptions)proposedOptions
6038 return proposedOptions|NSApplicationPresentationAutoHideToolbar;
6042 - (void)windowWillEnterFullScreen:(NSNotification *)notification
6044 fs_before_fs = fs_state;
6047 - (void)windowDidEnterFullScreen:(NSNotification *)notification
6049 [self setFSValue: FULLSCREEN_BOTH];
6050 if (! [self fsIsNative])
6052 [self windowDidBecomeKey:notification];
6053 [nonfs_window orderOut:self];
6055 else if (! FRAME_EXTERNAL_TOOL_BAR (emacsframe))
6056 [toolbar setVisible:NO];
6059 - (void)windowWillExitFullScreen:(NSNotification *)notification
6061 if (next_maximized != -1)
6062 fs_before_fs = next_maximized;
6065 - (void)windowDidExitFullScreen:(NSNotification *)notification
6067 [self setFSValue: fs_before_fs];
6069 [self updateCollectionBehaviour];
6070 if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
6072 [toolbar setVisible:YES];
6073 update_frame_tool_bar (emacsframe);
6074 [self updateFrameSize:YES];
6075 [[self window] display];
6078 [toolbar setVisible:NO];
6080 if (next_maximized != -1)
6081 [[self window] performZoom:self];
6086 return fs_is_native;
6089 - (BOOL)isFullscreen
6091 if (! fs_is_native) return nonfs_window != nil;
6092 #ifdef HAVE_NATIVE_FS
6093 return ([[self window] styleMask] & NSFullScreenWindowMask) != 0;
6099 #ifdef HAVE_NATIVE_FS
6100 - (void)updateCollectionBehaviour
6102 if (! [self isFullscreen])
6104 NSWindow *win = [self window];
6105 NSWindowCollectionBehavior b = [win collectionBehavior];
6106 if (ns_use_native_fullscreen)
6107 b |= NSWindowCollectionBehaviorFullScreenPrimary;
6109 b &= ~NSWindowCollectionBehaviorFullScreenPrimary;
6111 [win setCollectionBehavior: b];
6112 fs_is_native = ns_use_native_fullscreen;
6117 - (void)toggleFullScreen: (id)sender
6128 [[self window] toggleFullScreen:sender];
6133 onFirstScreen = [[w screen] isEqual:[[NSScreen screens] objectAtIndex:0]];
6136 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
6137 (FRAME_DEFAULT_FACE (f)),
6140 sz.width = FRAME_COLUMN_WIDTH (f);
6141 sz.height = FRAME_LINE_HEIGHT (f);
6143 if (fs_state != FULLSCREEN_BOTH)
6145 /* Hide dock and menubar if we are on the primary screen. */
6148 #if defined (NS_IMPL_COCOA) && \
6149 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
6150 NSApplicationPresentationOptions options
6151 = NSApplicationPresentationAutoHideDock
6152 | NSApplicationPresentationAutoHideMenuBar;
6154 [NSApp setPresentationOptions: options];
6156 [NSMenu setMenuBarVisible:NO];
6160 fw = [[EmacsFSWindow alloc]
6161 initWithContentRect:[w contentRectForFrameRect:wr]
6162 styleMask:NSBorderlessWindowMask
6163 backing:NSBackingStoreBuffered
6167 [fw setContentView:[w contentView]];
6168 [fw setTitle:[w title]];
6169 [fw setDelegate:self];
6170 [fw setAcceptsMouseMovedEvents: YES];
6171 [fw useOptimizedDrawing: YES];
6172 [fw setResizeIncrements: sz];
6173 [fw setBackgroundColor: col];
6174 if ([col alphaComponent] != 1.0)
6177 f->border_width = 0;
6178 FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
6179 tobar_height = FRAME_TOOLBAR_HEIGHT (f);
6180 FRAME_TOOLBAR_HEIGHT (f) = 0;
6184 [self windowWillEnterFullScreen:nil];
6185 [fw makeKeyAndOrderFront:NSApp];
6186 [fw makeFirstResponder:self];
6188 r = [fw frameRectForContentRect:[[fw screen] frame]];
6189 [fw setFrame: r display:YES animate:YES];
6190 [self windowDidEnterFullScreen:nil];
6201 #if defined (NS_IMPL_COCOA) && \
6202 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
6203 [NSApp setPresentationOptions: NSApplicationPresentationDefault];
6205 [NSMenu setMenuBarVisible:YES];
6209 [w setContentView:[fw contentView]];
6210 [w setResizeIncrements: sz];
6211 [w setBackgroundColor: col];
6212 if ([col alphaComponent] != 1.0)
6215 f->border_width = bwidth;
6216 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
6217 if (FRAME_EXTERNAL_TOOL_BAR (f))
6218 FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
6220 [self windowWillExitFullScreen:nil];
6221 [fw setFrame: [w frame] display:YES animate:YES];
6223 [w makeKeyAndOrderFront:NSApp];
6224 [self windowDidExitFullScreen:nil];
6225 [self updateFrameSize:YES];
6231 if (fs_state != emacsframe->want_fullscreen)
6233 if (fs_state == FULLSCREEN_BOTH)
6235 [self toggleFullScreen:self];
6238 switch (emacsframe->want_fullscreen)
6240 case FULLSCREEN_BOTH:
6241 [self toggleFullScreen:self];
6243 case FULLSCREEN_WIDTH:
6244 next_maximized = FULLSCREEN_WIDTH;
6245 if (fs_state != FULLSCREEN_BOTH)
6246 [[self window] performZoom:self];
6248 case FULLSCREEN_HEIGHT:
6249 next_maximized = FULLSCREEN_HEIGHT;
6250 if (fs_state != FULLSCREEN_BOTH)
6251 [[self window] performZoom:self];
6253 case FULLSCREEN_MAXIMIZED:
6254 next_maximized = FULLSCREEN_MAXIMIZED;
6255 if (fs_state != FULLSCREEN_BOTH)
6256 [[self window] performZoom:self];
6258 case FULLSCREEN_NONE:
6259 if (fs_state != FULLSCREEN_BOTH)
6261 next_maximized = FULLSCREEN_NONE;
6262 [[self window] performZoom:self];
6267 emacsframe->want_fullscreen = FULLSCREEN_NONE;
6272 - (void) setFSValue: (int)value
6274 Lisp_Object lval = Qnil;
6277 case FULLSCREEN_BOTH:
6280 case FULLSCREEN_WIDTH:
6283 case FULLSCREEN_HEIGHT:
6286 case FULLSCREEN_MAXIMIZED:
6290 store_frame_param (emacsframe, Qfullscreen, lval);
6294 - (void)mouseEntered: (NSEvent *)theEvent
6296 NSTRACE (mouseEntered);
6297 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
6301 - (void)mouseExited: (NSEvent *)theEvent
6303 Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL;
6305 NSTRACE (mouseExited);
6310 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
6312 if (emacsframe == hlinfo->mouse_face_mouse_frame)
6314 clear_mouse_face (hlinfo);
6315 hlinfo->mouse_face_mouse_frame = 0;
6323 if (context_menu_value == -1)
6324 context_menu_value = [sender tag];
6327 NSInteger tag = [sender tag];
6328 find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
6329 emacsframe->menu_bar_vector,
6333 ns_send_appdefined (-1);
6338 - (EmacsToolbar *)toolbar
6344 /* this gets called on toolbar button click */
6345 - toolbarClicked: (id)item
6348 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
6350 NSTRACE (toolbarClicked);
6355 /* send first event (for some reason two needed) */
6356 theEvent = [[self window] currentEvent];
6357 emacs_event->kind = TOOL_BAR_EVENT;
6358 XSETFRAME (emacs_event->arg, emacsframe);
6359 EV_TRAILER (theEvent);
6361 emacs_event->kind = TOOL_BAR_EVENT;
6362 /* XSETINT (emacs_event->code, 0); */
6363 emacs_event->arg = AREF (emacsframe->tool_bar_items,
6364 idx + TOOL_BAR_ITEM_KEY);
6365 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6366 EV_TRAILER (theEvent);
6371 - toggleToolbar: (id)sender
6376 emacs_event->kind = NS_NONKEY_EVENT;
6377 emacs_event->code = KEY_NS_TOGGLE_TOOLBAR;
6378 EV_TRAILER ((id)nil);
6383 - (void)drawRect: (NSRect)rect
6385 int x = NSMinX (rect), y = NSMinY (rect);
6386 int width = NSWidth (rect), height = NSHeight (rect);
6390 if (!emacsframe || !emacsframe->output_data.ns)
6393 ns_clear_frame_area (emacsframe, x, y, width, height);
6394 expose_frame (emacsframe, x, y, width, height);
6397 drawRect: may be called (at least in OS X 10.5) for invisible
6398 views as well for some reason. Thus, do not infer visibility
6401 emacsframe->async_visible = 1;
6402 emacsframe->async_iconified = 0;
6407 /* NSDraggingDestination protocol methods. Actually this is not really a
6408 protocol, but a category of Object. O well... */
6410 -(NSUInteger) draggingEntered: (id <NSDraggingInfo>) sender
6412 NSTRACE (draggingEntered);
6413 return NSDragOperationGeneric;
6417 -(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
6423 -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
6428 NSEvent *theEvent = [[self window] currentEvent];
6431 NSTRACE (performDragOperation);
6436 position = [self convertPoint: [sender draggingLocation] fromView: nil];
6437 x = lrint (position.x); y = lrint (position.y);
6439 pb = [sender draggingPasteboard];
6440 type = [pb availableTypeFromArray: ns_drag_types];
6445 else if ([type isEqualToString: NSFilenamesPboardType])
6448 NSEnumerator *fenum;
6451 if (!(files = [pb propertyListForType: type]))
6454 fenum = [files objectEnumerator];
6455 while ( (file = [fenum nextObject]) )
6457 emacs_event->kind = NS_NONKEY_EVENT;
6458 emacs_event->code = KEY_NS_DRAG_FILE;
6459 XSETINT (emacs_event->x, x);
6460 XSETINT (emacs_event->y, y);
6461 ns_input_file = append2 (ns_input_file,
6462 build_string ([file UTF8String]));
6463 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6464 EV_TRAILER (theEvent);
6468 else if ([type isEqualToString: NSURLPboardType])
6473 if (!(fileURL = [NSURL URLFromPasteboard: pb]) ||
6474 [fileURL isFileURL] == NO)
6477 file = [fileURL path];
6478 emacs_event->kind = NS_NONKEY_EVENT;
6479 emacs_event->code = KEY_NS_DRAG_FILE;
6480 XSETINT (emacs_event->x, x);
6481 XSETINT (emacs_event->y, y);
6482 ns_input_file = append2 (ns_input_file, build_string ([file UTF8String]));
6483 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6484 EV_TRAILER (theEvent);
6487 else if ([type isEqualToString: NSStringPboardType]
6488 || [type isEqualToString: NSTabularTextPboardType])
6492 if (! (data = [pb stringForType: type]))
6495 emacs_event->kind = NS_NONKEY_EVENT;
6496 emacs_event->code = KEY_NS_DRAG_TEXT;
6497 XSETINT (emacs_event->x, x);
6498 XSETINT (emacs_event->y, y);
6499 ns_input_text = build_string ([data UTF8String]);
6500 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6501 EV_TRAILER (theEvent);
6504 else if ([type isEqualToString: NSColorPboardType])
6506 NSColor *c = [NSColor colorFromPasteboard: pb];
6507 emacs_event->kind = NS_NONKEY_EVENT;
6508 emacs_event->code = KEY_NS_DRAG_COLOR;
6509 XSETINT (emacs_event->x, x);
6510 XSETINT (emacs_event->y, y);
6511 ns_input_color = ns_color_to_lisp (c);
6512 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6513 EV_TRAILER (theEvent);
6516 else if ([type isEqualToString: NSFontPboardType])
6518 /* impl based on GNUstep NSTextView.m */
6519 NSData *data = [pb dataForType: NSFontPboardType];
6520 NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data];
6521 NSFont *font = [dict objectForKey: NSFontAttributeName];
6527 emacs_event->kind = NS_NONKEY_EVENT;
6528 emacs_event->code = KEY_NS_CHANGE_FONT;
6529 XSETINT (emacs_event->x, x);
6530 XSETINT (emacs_event->y, y);
6531 ns_input_font = build_string ([[font fontName] UTF8String]);
6532 snprintf (fontSize, 10, "%f", [font pointSize]);
6533 ns_input_fontsize = build_string (fontSize);
6534 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6535 EV_TRAILER (theEvent);
6540 error ("Invalid data type in dragging pasteboard.");
6546 - (id) validRequestorForSendType: (NSString *)typeSent
6547 returnType: (NSString *)typeReturned
6549 NSTRACE (validRequestorForSendType);
6550 if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound
6551 && typeReturned == nil)
6553 if (! NILP (ns_get_local_selection (QPRIMARY, QUTF8_STRING)))
6557 return [super validRequestorForSendType: typeSent
6558 returnType: typeReturned];
6562 /* The next two methods are part of NSServicesRequests informal protocol,
6563 supposedly called when a services menu item is chosen from this app.
6564 But this should not happen because we override the services menu with our
6565 own entries which call ns-perform-service.
6566 Nonetheless, it appeared to happen (under strange circumstances): bug#1435.
6567 So let's at least stub them out until further investigation can be done. */
6569 - (BOOL) readSelectionFromPasteboard: (NSPasteboard *)pb
6571 /* we could call ns_string_from_pasteboard(pboard) here but then it should
6572 be written into the buffer in place of the existing selection..
6573 ordinary service calls go through functions defined in ns-win.el */
6577 - (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types
6579 NSArray *typesDeclared;
6582 /* We only support NSStringPboardType */
6583 if ([types containsObject:NSStringPboardType] == NO) {
6587 val = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
6588 if (CONSP (val) && SYMBOLP (XCAR (val)))
6591 if (CONSP (val) && NILP (XCDR (val)))
6594 if (! STRINGP (val))
6597 typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
6598 [pb declareTypes:typesDeclared owner:nil];
6599 ns_string_to_pasteboard (pb, val);
6604 /* setMini =YES means set from internal (gives a finder icon), NO means set nil
6605 (gives a miniaturized version of the window); currently we use the latter for
6606 frames whose active buffer doesn't correspond to any file
6607 (e.g., '*scratch*') */
6608 - setMiniwindowImage: (BOOL) setMini
6610 id image = [[self window] miniwindowImage];
6611 NSTRACE (setMiniwindowImage);
6613 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
6614 about "AppleDockIconEnabled" notwithstanding, however the set message
6615 below has its effect nonetheless. */
6616 if (image != emacsframe->output_data.ns->miniimage)
6618 if (image && [image isKindOfClass: [EmacsImage class]])
6620 [[self window] setMiniwindowImage:
6621 setMini ? emacsframe->output_data.ns->miniimage : nil];
6628 - (void) setRows: (int) r andColumns: (int) c
6634 @end /* EmacsView */
6638 /* ==========================================================================
6640 EmacsWindow implementation
6642 ========================================================================== */
6644 @implementation EmacsWindow
6646 #ifdef NS_IMPL_COCOA
6647 - (id)accessibilityAttributeValue:(NSString *)attribute
6649 Lisp_Object str = Qnil;
6650 struct frame *f = SELECTED_FRAME ();
6651 struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contents);
6653 if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
6654 return NSAccessibilityTextFieldRole;
6656 if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]
6657 && curbuf && ! NILP (BVAR (curbuf, mark_active)))
6659 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
6661 else if (curbuf && [attribute isEqualToString:NSAccessibilityValueAttribute])
6663 if (! NILP (BVAR (curbuf, mark_active)))
6664 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
6668 ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf);
6669 ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte;
6670 ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf);
6672 if (! NILP (BVAR (curbuf, enable_multibyte_characters)))
6673 str = make_uninit_multibyte_string (range, byte_range);
6675 str = make_uninit_string (range);
6676 /* To check: This returns emacs-utf-8, which is a superset of utf-8.
6677 Is this a problem? */
6678 memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range);
6685 if (CONSP (str) && SYMBOLP (XCAR (str)))
6688 if (CONSP (str) && NILP (XCDR (str)))
6693 const char *utfStr = SSDATA (str);
6694 NSString *nsStr = [NSString stringWithUTF8String: utfStr];
6699 return [super accessibilityAttributeValue:attribute];
6701 #endif /* NS_IMPL_COCOA */
6703 /* If we have multiple monitors, one above the other, we don't want to
6704 restrict the height to just one monitor. So we override this. */
6705 - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
6707 /* When making the frame visible for the first time or if there is just
6708 one screen, we want to constrain. Other times not. */
6709 NSUInteger nr_screens = [[NSScreen screens] count];
6710 struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
6711 NSTRACE (constrainFrameRect);
6713 if (nr_screens == 1)
6715 NSRect r = [super constrainFrameRect:frameRect toScreen:screen];
6719 if (f->output_data.ns->dont_constrain
6720 || ns_menu_bar_should_be_hidden ())
6723 f->output_data.ns->dont_constrain = 1;
6724 return [super constrainFrameRect:frameRect toScreen:screen];
6727 @end /* EmacsWindow */
6730 @implementation EmacsFSWindow
6732 - (BOOL)canBecomeKeyWindow
6737 - (BOOL)canBecomeMainWindow
6744 /* ==========================================================================
6746 EmacsScroller implementation
6748 ========================================================================== */
6751 @implementation EmacsScroller
6753 /* for repeat button push */
6754 #define SCROLL_BAR_FIRST_DELAY 0.5
6755 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
6757 + (CGFloat) scrollerWidth
6759 /* TODO: if we want to allow variable widths, this is the place to do it,
6760 however neither GNUstep nor Cocoa support it very well */
6761 return [NSScroller scrollerWidth];
6765 - initFrame: (NSRect )r window: (Lisp_Object)nwin
6767 NSTRACE (EmacsScroller_initFrame);
6769 r.size.width = [EmacsScroller scrollerWidth];
6770 [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
6771 [self setContinuous: YES];
6772 [self setEnabled: YES];
6774 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
6775 locked against the top and bottom edges, and right edge on OS X, where
6776 scrollers are on right. */
6777 #ifdef NS_IMPL_GNUSTEP
6778 [self setAutoresizingMask: NSViewMaxXMargin | NSViewHeightSizable];
6780 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
6785 pixel_height = NSHeight (r);
6786 if (pixel_height == 0) pixel_height = 1;
6787 min_portion = 20 / pixel_height;
6789 frame = XFRAME (XWINDOW (win)->frame);
6790 if (FRAME_LIVE_P (frame))
6793 EmacsView *view = FRAME_NS_VIEW (frame);
6794 NSView *sview = [[view window] contentView];
6795 NSArray *subs = [sview subviews];
6797 /* disable optimization stopping redraw of other scrollbars */
6798 view->scrollbarsNeedingUpdate = 0;
6799 for (i =[subs count]-1; i >= 0; i--)
6800 if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]])
6801 view->scrollbarsNeedingUpdate++;
6802 [sview addSubview: self];
6805 /* [self setFrame: r]; */
6811 - (void)setFrame: (NSRect)newRect
6813 NSTRACE (EmacsScroller_setFrame);
6814 /* block_input (); */
6815 pixel_height = NSHeight (newRect);
6816 if (pixel_height == 0) pixel_height = 1;
6817 min_portion = 20 / pixel_height;
6818 [super setFrame: newRect];
6820 /* unblock_input (); */
6826 NSTRACE (EmacsScroller_dealloc);
6828 wset_vertical_scroll_bar (XWINDOW (win), Qnil);
6856 /* ensure other scrollbar updates after deletion */
6857 view = (EmacsView *)FRAME_NS_VIEW (frame);
6859 view->scrollbarsNeedingUpdate++;
6860 [self removeFromSuperview];
6868 - (void)resetCursorRects
6870 NSRect visible = [self visibleRect];
6871 NSTRACE (resetCursorRects);
6873 if (!NSIsEmptyRect (visible))
6874 [self addCursorRect: visible cursor: [NSCursor arrowCursor]];
6875 [[NSCursor arrowCursor] setOnMouseEntered: YES];
6879 - (int) checkSamePosition: (int) position portion: (int) portion
6882 return em_position ==position && em_portion ==portion && em_whole ==whole
6883 && portion != whole; /* needed for resize empty buf */
6887 - setPosition: (int)position portion: (int)portion whole: (int)whole
6889 NSTRACE (setPosition);
6891 em_position = position;
6892 em_portion = portion;
6895 if (portion >= whole)
6897 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
6898 [self setKnobProportion: 1.0];
6899 [self setDoubleValue: 1.0];
6901 [self setFloatValue: 0.0 knobProportion: 1.0];
6907 portion = max ((float)whole*min_portion/pixel_height, portion);
6908 pos = (float)position / (whole - portion);
6909 por = (float)portion/whole;
6910 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
6911 [self setKnobProportion: por];
6912 [self setDoubleValue: pos];
6914 [self setFloatValue: pos knobProportion: por];
6918 /* Events may come here even if the event loop is not running.
6919 If we don't enter the event loop, the scroll bar will not update.
6920 So send SIGIO to ourselves. */
6921 if (apploopnr == 0) raise (SIGIO);
6926 /* FIXME: unused at moment (see ns_mouse_position) at the moment because
6927 drag events will go directly to the EmacsScroller. Leaving in for now. */
6928 -(void)getMouseMotionPart: (int *)part window: (Lisp_Object *)window
6929 x: (Lisp_Object *)x y: ( Lisp_Object *)y
6931 *part = last_hit_part;
6933 XSETINT (*y, pixel_height);
6934 if ([self floatValue] > 0.999)
6935 XSETINT (*x, pixel_height);
6937 XSETINT (*x, pixel_height * [self floatValue]);
6941 /* set up emacs_event */
6942 - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
6947 emacs_event->part = last_hit_part;
6948 emacs_event->code = 0;
6949 emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier;
6950 emacs_event->frame_or_window = win;
6951 emacs_event->timestamp = EV_TIMESTAMP (e);
6952 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
6953 emacs_event->arg = Qnil;
6954 XSETINT (emacs_event->x, loc * pixel_height);
6955 XSETINT (emacs_event->y, pixel_height-20);
6959 n_emacs_events_pending++;
6960 kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
6963 hold_event (emacs_event);
6964 EVENT_INIT (*emacs_event);
6965 ns_send_appdefined (-1);
6969 /* called manually thru timer to implement repeated button action w/hold-down */
6970 - repeatScroll: (NSTimer *)scrollEntry
6972 NSEvent *e = [[self window] currentEvent];
6973 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
6974 BOOL inKnob = [self testPart: p] == NSScrollerKnob;
6976 /* clear timer if need be */
6977 if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
6979 [scroll_repeat_entry invalidate];
6980 [scroll_repeat_entry release];
6981 scroll_repeat_entry = nil;
6987 = [[NSTimer scheduledTimerWithTimeInterval:
6988 SCROLL_BAR_CONTINUOUS_DELAY
6990 selector: @selector (repeatScroll:)
6996 [self sendScrollEventAtLoc: 0 fromEvent: e];
7001 /* Asynchronous mouse tracking for scroller. This allows us to dispatch
7002 mouseDragged events without going into a modal loop. */
7003 - (void)mouseDown: (NSEvent *)e
7006 /* hitPart is only updated AFTER event is passed on */
7007 NSScrollerPart part = [self testPart: [e locationInWindow]];
7008 double inc = 0.0, loc, kloc, pos;
7011 NSTRACE (EmacsScroller_mouseDown);
7015 case NSScrollerDecrementPage:
7016 last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
7017 case NSScrollerIncrementPage:
7018 last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
7019 case NSScrollerDecrementLine:
7020 last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
7021 case NSScrollerIncrementLine:
7022 last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
7023 case NSScrollerKnob:
7024 last_hit_part = scroll_bar_handle; break;
7025 case NSScrollerKnobSlot: /* GNUstep-only */
7026 last_hit_part = scroll_bar_move_ratio; break;
7027 default: /* NSScrollerNoPart? */
7028 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %ld\n",
7035 pos = 0; /* ignored */
7037 /* set a timer to repeat, as we can't let superclass do this modally */
7039 = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY
7041 selector: @selector (repeatScroll:)
7048 /* handle, or on GNUstep possibly slot */
7049 NSEvent *fake_event;
7051 /* compute float loc in slot and mouse offset on knob */
7052 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
7054 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
7060 else if (loc >= NSHeight (sr))
7062 loc = NSHeight (sr);
7070 kr = [self convertRect: [self rectForPart: NSScrollerKnob]
7072 kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
7074 last_mouse_offset = kloc;
7076 /* if knob, tell emacs a location offset by knob pos
7077 (to indicate top of handle) */
7078 if (part == NSScrollerKnob)
7079 pos = (loc - last_mouse_offset) / NSHeight (sr);
7081 /* else this is a slot click on GNUstep: go straight there */
7082 pos = loc / NSHeight (sr);
7084 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
7085 fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
7086 location: [e locationInWindow]
7087 modifierFlags: [e modifierFlags]
7088 timestamp: [e timestamp]
7089 windowNumber: [e windowNumber]
7090 context: [e context]
7091 eventNumber: [e eventNumber]
7092 clickCount: [e clickCount]
7093 pressure: [e pressure]];
7094 [super mouseUp: fake_event];
7097 if (part != NSScrollerKnob)
7098 [self sendScrollEventAtLoc: pos fromEvent: e];
7102 /* Called as we manually track scroller drags, rather than superclass. */
7103 - (void)mouseDragged: (NSEvent *)e
7109 NSTRACE (EmacsScroller_mouseDragged);
7111 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
7113 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
7120 else if (loc >= NSHeight (sr) + last_mouse_offset)
7122 loc = NSHeight (sr) + last_mouse_offset;
7126 pos = /*(edge ? loc :*/ (loc - last_mouse_offset) / NSHeight (sr);
7127 [self sendScrollEventAtLoc: pos fromEvent: e];
7131 - (void)mouseUp: (NSEvent *)e
7133 if (scroll_repeat_entry)
7135 [scroll_repeat_entry invalidate];
7136 [scroll_repeat_entry release];
7137 scroll_repeat_entry = nil;
7143 /* treat scrollwheel events in the bar as though they were in the main window */
7144 - (void) scrollWheel: (NSEvent *)theEvent
7146 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
7147 [view mouseDown: theEvent];
7150 @end /* EmacsScroller */
7155 /* ==========================================================================
7157 Font-related functions; these used to be in nsfaces.m
7159 ========================================================================== */
7163 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7165 struct font *font = XFONT_OBJECT (font_object);
7168 fontset = fontset_from_font (font_object);
7169 FRAME_FONTSET (f) = fontset;
7171 if (FRAME_FONT (f) == font)
7172 /* This font is already set in frame F. There's nothing more to
7176 FRAME_FONT (f) = font;
7178 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
7179 FRAME_COLUMN_WIDTH (f) = font->average_width;
7180 FRAME_LINE_HEIGHT (f) = font->height;
7182 compute_fringe_widths (f, 1);
7184 /* Compute the scroll bar width in character columns. */
7185 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
7187 int wid = FRAME_COLUMN_WIDTH (f);
7188 FRAME_CONFIG_SCROLL_BAR_COLS (f)
7189 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
7193 int wid = FRAME_COLUMN_WIDTH (f);
7194 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
7197 /* Now make the frame display the given font. */
7198 if (FRAME_NS_WINDOW (f) != 0)
7199 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
7205 /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
7206 /* Note: ns_font_to_xlfd and ns_fontname_to_xlfd no longer needed, removed
7210 ns_xlfd_to_fontname (const char *xlfd)
7211 /* --------------------------------------------------------------------------
7212 Convert an X font name (XLFD) to an NS font name.
7213 Only family is used.
7214 The string returned is temporarily allocated.
7215 -------------------------------------------------------------------------- */
7217 char *name = xmalloc (180);
7221 if (!strncmp (xlfd, "--", 2))
7222 sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
7224 sscanf (xlfd, "-%*[^-]-%[^-]179-", name);
7226 /* stopgap for malformed XLFD input */
7227 if (strlen (name) == 0)
7228 strcpy (name, "Monaco");
7230 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
7231 also uppercase after '-' or ' ' */
7232 name[0] = c_toupper (name[0]);
7233 for (len =strlen (name), i =0; i<len; i++)
7239 name[i+1] = c_toupper (name[i+1]);
7241 else if (name[i] == '_')
7245 name[i+1] = c_toupper (name[i+1]);
7248 /*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
7249 ret = [[NSString stringWithUTF8String: name] UTF8String];
7256 syms_of_nsterm (void)
7258 NSTRACE (syms_of_nsterm);
7260 ns_antialias_threshold = 10.0;
7262 /* from 23+ we need to tell emacs what modifiers there are.. */
7263 DEFSYM (Qmodifier_value, "modifier-value");
7264 DEFSYM (Qalt, "alt");
7265 DEFSYM (Qhyper, "hyper");
7266 DEFSYM (Qmeta, "meta");
7267 DEFSYM (Qsuper, "super");
7268 DEFSYM (Qcontrol, "control");
7269 DEFSYM (QUTF8_STRING, "UTF8_STRING");
7271 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
7272 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
7273 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
7274 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
7275 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
7277 DEFVAR_LISP ("ns-input-file", ns_input_file,
7278 "The file specified in the last NS event.");
7279 ns_input_file =Qnil;
7281 DEFVAR_LISP ("ns-input-text", ns_input_text,
7282 "The data received in the last NS text drag event.");
7283 ns_input_text =Qnil;
7285 DEFVAR_LISP ("ns-working-text", ns_working_text,
7286 "String for visualizing working composition sequence.");
7287 ns_working_text =Qnil;
7289 DEFVAR_LISP ("ns-input-font", ns_input_font,
7290 "The font specified in the last NS event.");
7291 ns_input_font =Qnil;
7293 DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize,
7294 "The fontsize specified in the last NS event.");
7295 ns_input_fontsize =Qnil;
7297 DEFVAR_LISP ("ns-input-line", ns_input_line,
7298 "The line specified in the last NS event.");
7299 ns_input_line =Qnil;
7301 DEFVAR_LISP ("ns-input-color", ns_input_color,
7302 "The color specified in the last NS event.");
7303 ns_input_color =Qnil;
7305 DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
7306 "The service name specified in the last NS event.");
7307 ns_input_spi_name =Qnil;
7309 DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg,
7310 "The service argument specified in the last NS event.");
7311 ns_input_spi_arg =Qnil;
7313 DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier,
7314 "This variable describes the behavior of the alternate or option key.\n\
7315 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7316 Set to none means that the alternate / option key is not interpreted by Emacs\n\
7317 at all, allowing it to be used at a lower level for accented character entry.");
7318 ns_alternate_modifier = Qmeta;
7320 DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier,
7321 "This variable describes the behavior of the right alternate or option key.\n\
7322 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7323 Set to left means be the same key as `ns-alternate-modifier'.\n\
7324 Set to none means that the alternate / option key is not interpreted by Emacs\n\
7325 at all, allowing it to be used at a lower level for accented character entry.");
7326 ns_right_alternate_modifier = Qleft;
7328 DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
7329 "This variable describes the behavior of the command key.\n\
7330 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
7331 ns_command_modifier = Qsuper;
7333 DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
7334 "This variable describes the behavior of the right command key.\n\
7335 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7336 Set to left means be the same key as `ns-command-modifier'.\n\
7337 Set to none means that the command / option key is not interpreted by Emacs\n\
7338 at all, allowing it to be used at a lower level for accented character entry.");
7339 ns_right_command_modifier = Qleft;
7341 DEFVAR_LISP ("ns-control-modifier", ns_control_modifier,
7342 "This variable describes the behavior of the control key.\n\
7343 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
7344 ns_control_modifier = Qcontrol;
7346 DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier,
7347 "This variable describes the behavior of the right control key.\n\
7348 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7349 Set to left means be the same key as `ns-control-modifier'.\n\
7350 Set to none means that the control / option key is not interpreted by Emacs\n\
7351 at all, allowing it to be used at a lower level for accented character entry.");
7352 ns_right_control_modifier = Qleft;
7354 DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
7355 "This variable describes the behavior of the function key (on laptops).\n\
7356 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7357 Set to none means that the function key is not interpreted by Emacs at all,\n\
7358 allowing it to be used at a lower level for accented character entry.");
7359 ns_function_modifier = Qnone;
7361 DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
7362 "Non-nil (the default) means to render text antialiased.");
7363 ns_antialias_text = Qt;
7365 DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
7366 "Whether to confirm application quit using dialog.");
7367 ns_confirm_quit = Qnil;
7369 staticpro (&ns_display_name_list);
7370 ns_display_name_list = Qnil;
7372 staticpro (&last_mouse_motion_frame);
7373 last_mouse_motion_frame = Qnil;
7375 DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
7376 doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
7377 Only works on OSX 10.6 or later. */);
7378 ns_auto_hide_menu_bar = Qnil;
7380 DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen,
7381 doc: /*Non-nil means to use native fullscreen on OSX >= 10.7.
7382 Nil means use fullscreen the old (< 10.7) way. The old way works better with
7383 multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7.
7384 Default is t for OSX >= 10.7, nil otherwise. */);
7385 #ifdef HAVE_NATIVE_FS
7386 ns_use_native_fullscreen = YES;
7388 ns_use_native_fullscreen = NO;
7390 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
7392 /* TODO: move to common code */
7393 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
7394 doc: /* Which toolkit scroll bars Emacs uses, if any.
7395 A value of nil means Emacs doesn't use toolkit scroll bars.
7396 With the X Window system, the value is a symbol describing the
7397 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
7398 With MS Windows or Nextstep, the value is t. */);
7399 Vx_toolkit_scroll_bars = Qt;
7401 DEFVAR_BOOL ("x-use-underline-position-properties",
7402 x_use_underline_position_properties,
7403 doc: /*Non-nil means make use of UNDERLINE_POSITION font properties.
7404 A value of nil means ignore them. If you encounter fonts with bogus
7405 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
7406 to 4.1, set this to nil. */);
7407 x_use_underline_position_properties = 0;
7409 DEFVAR_BOOL ("x-underline-at-descent-line",
7410 x_underline_at_descent_line,
7411 doc: /* Non-nil means to draw the underline at the same place as the descent line.
7412 A value of nil means to draw the underline according to the value of the
7413 variable `x-use-underline-position-properties', which is usually at the
7414 baseline level. The default value is nil. */);
7415 x_underline_at_descent_line = 0;
7417 /* Tell emacs about this window system. */
7418 Fprovide (intern ("ns"), Qnil);