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"
63 #ifdef NS_IMPL_GNUSTEP
69 int term_trace_num = 0;
70 #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
71 __FILE__, __LINE__, ++term_trace_num)
76 extern NSString *NSMenuDidBeginTrackingNotification;
78 /* ==========================================================================
82 ========================================================================== */
84 /* Convert a symbol indexed with an NSxxx value to a value as defined
85 in keyboard.c (lispy_function_key). I hope this is a correct way
87 static unsigned convert_ns_to_X_keysym[] =
89 NSHomeFunctionKey, 0x50,
90 NSLeftArrowFunctionKey, 0x51,
91 NSUpArrowFunctionKey, 0x52,
92 NSRightArrowFunctionKey, 0x53,
93 NSDownArrowFunctionKey, 0x54,
94 NSPageUpFunctionKey, 0x55,
95 NSPageDownFunctionKey, 0x56,
96 NSEndFunctionKey, 0x57,
97 NSBeginFunctionKey, 0x58,
98 NSSelectFunctionKey, 0x60,
99 NSPrintFunctionKey, 0x61,
100 NSClearLineFunctionKey, 0x0B,
101 NSExecuteFunctionKey, 0x62,
102 NSInsertFunctionKey, 0x63,
103 NSUndoFunctionKey, 0x65,
104 NSRedoFunctionKey, 0x66,
105 NSMenuFunctionKey, 0x67,
106 NSFindFunctionKey, 0x68,
107 NSHelpFunctionKey, 0x6A,
108 NSBreakFunctionKey, 0x6B,
110 NSF1FunctionKey, 0xBE,
111 NSF2FunctionKey, 0xBF,
112 NSF3FunctionKey, 0xC0,
113 NSF4FunctionKey, 0xC1,
114 NSF5FunctionKey, 0xC2,
115 NSF6FunctionKey, 0xC3,
116 NSF7FunctionKey, 0xC4,
117 NSF8FunctionKey, 0xC5,
118 NSF9FunctionKey, 0xC6,
119 NSF10FunctionKey, 0xC7,
120 NSF11FunctionKey, 0xC8,
121 NSF12FunctionKey, 0xC9,
122 NSF13FunctionKey, 0xCA,
123 NSF14FunctionKey, 0xCB,
124 NSF15FunctionKey, 0xCC,
125 NSF16FunctionKey, 0xCD,
126 NSF17FunctionKey, 0xCE,
127 NSF18FunctionKey, 0xCF,
128 NSF19FunctionKey, 0xD0,
129 NSF20FunctionKey, 0xD1,
130 NSF21FunctionKey, 0xD2,
131 NSF22FunctionKey, 0xD3,
132 NSF23FunctionKey, 0xD4,
133 NSF24FunctionKey, 0xD5,
135 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
136 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
137 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
139 NSTabCharacter, 0x09,
140 0x19, 0x09, /* left tab->regular since pass shift */
141 NSCarriageReturnCharacter, 0x0D,
142 NSNewlineCharacter, 0x0D,
143 NSEnterCharacter, 0x8D,
145 0x41|NSNumericPadKeyMask, 0xAE, /* KP_Decimal */
146 0x43|NSNumericPadKeyMask, 0xAA, /* KP_Multiply */
147 0x45|NSNumericPadKeyMask, 0xAB, /* KP_Add */
148 0x4B|NSNumericPadKeyMask, 0xAF, /* KP_Divide */
149 0x4E|NSNumericPadKeyMask, 0xAD, /* KP_Subtract */
150 0x51|NSNumericPadKeyMask, 0xBD, /* KP_Equal */
151 0x52|NSNumericPadKeyMask, 0xB0, /* KP_0 */
152 0x53|NSNumericPadKeyMask, 0xB1, /* KP_1 */
153 0x54|NSNumericPadKeyMask, 0xB2, /* KP_2 */
154 0x55|NSNumericPadKeyMask, 0xB3, /* KP_3 */
155 0x56|NSNumericPadKeyMask, 0xB4, /* KP_4 */
156 0x57|NSNumericPadKeyMask, 0xB5, /* KP_5 */
157 0x58|NSNumericPadKeyMask, 0xB6, /* KP_6 */
158 0x59|NSNumericPadKeyMask, 0xB7, /* KP_7 */
159 0x5B|NSNumericPadKeyMask, 0xB8, /* KP_8 */
160 0x5C|NSNumericPadKeyMask, 0xB9, /* KP_9 */
162 0x1B, 0x1B /* escape */
165 static Lisp_Object Qmodifier_value;
166 Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
167 extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft;
169 static Lisp_Object QUTF8_STRING;
171 /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
172 the maximum font size to NOT antialias. On GNUstep there is currently
173 no way to control this behavior. */
174 float ns_antialias_threshold;
176 /* Used to pick up AppleHighlightColor on OS X */
177 NSString *ns_selection_color;
179 NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
180 NSString *ns_app_name = @"Emacs"; /* default changed later */
182 /* Display variables */
183 struct ns_display_info *x_display_list; /* Chain of existing displays */
184 Lisp_Object ns_display_name_list;
185 long context_menu_value = 0;
188 NSPoint last_mouse_motion_position;
189 static NSRect last_mouse_glyph;
190 static Time last_mouse_movement_time = 0;
191 static Lisp_Object last_mouse_motion_frame;
192 static EmacsScroller *last_mouse_scroll_bar = nil;
193 static struct frame *ns_updating_frame;
194 static NSView *focus_view = NULL;
195 static int ns_window_num = 0;
196 #ifdef NS_IMPL_GNUSTEP
199 static BOOL gsaved = NO;
200 static BOOL ns_fake_keydown = NO;
201 int ns_tmp_flags; /* FIXME */
202 struct nsfont_info *ns_tmp_font; /* FIXME */
204 static BOOL ns_menu_bar_is_hidden = NO;
206 /*static int debug_lock = 0; */
209 static BOOL send_appdefined = YES;
210 #define NO_APPDEFINED_DATA (-8)
211 static int last_appdefined_event_data = NO_APPDEFINED_DATA;
212 static NSTimer *timed_entry = 0;
213 static NSTimer *scroll_repeat_entry = nil;
214 static fd_set select_readfds, select_writefds;
215 enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 };
216 static int select_nfds = 0, select_valid = 0;
217 static struct timespec select_timeout = { 0, 0 };
218 static int selfds[2] = { -1, -1 };
219 static pthread_mutex_t select_mutex;
220 static int apploopnr = 0;
221 static NSAutoreleasePool *outerpool;
222 static struct input_event *emacs_event = NULL;
223 static struct input_event *q_event_ptr = NULL;
224 static int n_emacs_events_pending = 0;
225 static NSMutableArray *ns_pending_files, *ns_pending_service_names,
226 *ns_pending_service_args;
227 static BOOL ns_do_open_file = NO;
228 static BOOL ns_last_use_native_fullscreen;
231 struct input_event *q;
239 * State for pending menu activation:
240 * MENU_NONE Normal state
241 * MENU_PENDING A menu has been clicked on, but has been canceled so we can
242 * run lisp to update the menu.
243 * MENU_OPENING Menu is up to date, and the click event is redone so the menu
247 #define MENU_PENDING 1
248 #define MENU_OPENING 2
249 static int menu_will_open_state = MENU_NONE;
251 /* Saved position for menu click. */
252 static CGPoint menu_mouse_point;
255 /* Convert modifiers in a NeXTstep event to emacs style modifiers. */
256 #define NS_FUNCTION_KEY_MASK 0x800000
257 #define NSLeftControlKeyMask (0x000001 | NSControlKeyMask)
258 #define NSRightControlKeyMask (0x002000 | NSControlKeyMask)
259 #define NSLeftCommandKeyMask (0x000008 | NSCommandKeyMask)
260 #define NSRightCommandKeyMask (0x000010 | NSCommandKeyMask)
261 #define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
262 #define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
263 #define EV_MODIFIERS(e) \
264 ((([e modifierFlags] & NSHelpKeyMask) ? \
265 hyper_modifier : 0) \
266 | (!EQ (ns_right_alternate_modifier, Qleft) && \
267 (([e modifierFlags] & NSRightAlternateKeyMask) \
268 == NSRightAlternateKeyMask) ? \
269 parse_solitary_modifier (ns_right_alternate_modifier) : 0) \
270 | (([e modifierFlags] & NSAlternateKeyMask) ? \
271 parse_solitary_modifier (ns_alternate_modifier) : 0) \
272 | (([e modifierFlags] & NSShiftKeyMask) ? \
273 shift_modifier : 0) \
274 | (!EQ (ns_right_control_modifier, Qleft) && \
275 (([e modifierFlags] & NSRightControlKeyMask) \
276 == NSRightControlKeyMask) ? \
277 parse_solitary_modifier (ns_right_control_modifier) : 0) \
278 | (([e modifierFlags] & NSControlKeyMask) ? \
279 parse_solitary_modifier (ns_control_modifier) : 0) \
280 | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \
281 parse_solitary_modifier (ns_function_modifier) : 0) \
282 | (!EQ (ns_right_command_modifier, Qleft) && \
283 (([e modifierFlags] & NSRightCommandKeyMask) \
284 == NSRightCommandKeyMask) ? \
285 parse_solitary_modifier (ns_right_command_modifier) : 0) \
286 | (([e modifierFlags] & NSCommandKeyMask) ? \
287 parse_solitary_modifier (ns_command_modifier):0))
289 #define EV_UDMODIFIERS(e) \
290 ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
291 | (([e type] == NSRightMouseDown) ? down_modifier : 0) \
292 | (([e type] == NSOtherMouseDown) ? down_modifier : 0) \
293 | (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
294 | (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
295 | (([e type] == NSOtherMouseDragged) ? down_modifier : 0) \
296 | (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
297 | (([e type] == NSRightMouseUp) ? up_modifier : 0) \
298 | (([e type] == NSOtherMouseUp) ? up_modifier : 0))
300 #define EV_BUTTON(e) \
301 ((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
302 (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : \
303 [e buttonNumber] - 1)
305 /* Convert the time field to a timestamp in milliseconds. */
306 #define EV_TIMESTAMP(e) ([e timestamp] * 1000)
308 /* This is a piece of code which is common to all the event handling
309 methods. Maybe it should even be a function. */
310 #define EV_TRAILER(e) \
312 XSETFRAME (emacs_event->frame_or_window, emacsframe); \
316 #define EV_TRAILER2(e) \
318 if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
321 n_emacs_events_pending++; \
322 kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
325 hold_event (emacs_event); \
326 EVENT_INIT (*emacs_event); \
327 ns_send_appdefined (-1); \
330 /* TODO: get rid of need for these forward declarations */
331 static void ns_condemn_scroll_bars (struct frame *f);
332 static void ns_judge_scroll_bars (struct frame *f);
333 void x_set_frame_alpha (struct frame *f);
336 /* ==========================================================================
340 ========================================================================== */
343 hold_event (struct input_event *event)
345 if (hold_event_q.nr == hold_event_q.cap)
347 if (hold_event_q.cap == 0) hold_event_q.cap = 10;
348 else hold_event_q.cap *= 2;
350 xrealloc (hold_event_q.q, hold_event_q.cap * sizeof *hold_event_q.q);
353 hold_event_q.q[hold_event_q.nr++] = *event;
354 /* Make sure ns_read_socket is called, i.e. we have input. */
356 send_appdefined = YES;
360 append2 (Lisp_Object list, Lisp_Object item)
361 /* --------------------------------------------------------------------------
362 Utility to append to a list
363 -------------------------------------------------------------------------- */
365 Lisp_Object array[2];
367 array[1] = list1 (item);
368 return Fnconc (2, &array[0]);
373 ns_etc_directory (void)
374 /* If running as a self-contained app bundle, return as a string the
375 filename of the etc directory, if present; else nil. */
377 NSBundle *bundle = [NSBundle mainBundle];
378 NSString *resourceDir = [bundle resourcePath];
379 NSString *resourcePath;
380 NSFileManager *fileManager = [NSFileManager defaultManager];
383 resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"];
384 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
386 if (isDir) return [resourcePath UTF8String];
394 /* If running as a self-contained app bundle, return as a path string
395 the filenames of the libexec and bin directories, ie libexec:bin.
396 Otherwise, return nil.
397 Normally, Emacs does not add its own bin/ directory to the PATH.
398 However, a self-contained NS build has a different layout, with
399 bin/ and libexec/ subdirectories in the directory that contains
401 We put libexec first, because init_callproc_1 uses the first
402 element to initialize exec-directory. An alternative would be
403 for init_callproc to check for invocation-directory/libexec.
406 NSBundle *bundle = [NSBundle mainBundle];
407 NSString *resourceDir = [bundle resourcePath];
408 NSString *binDir = [bundle bundlePath];
409 NSString *resourcePath, *resourcePaths;
411 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
412 NSFileManager *fileManager = [NSFileManager defaultManager];
414 NSEnumerator *pathEnum;
417 range = [resourceDir rangeOfString: @"Contents"];
418 if (range.location != NSNotFound)
420 binDir = [binDir stringByAppendingPathComponent: @"Contents"];
422 binDir = [binDir stringByAppendingPathComponent: @"MacOS"];
426 paths = [binDir stringsByAppendingPaths:
427 [NSArray arrayWithObjects: @"libexec", @"bin", nil]];
428 pathEnum = [paths objectEnumerator];
431 while ((resourcePath = [pathEnum nextObject]))
433 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
436 if ([resourcePaths length] > 0)
438 = [resourcePaths stringByAppendingString: pathSeparator];
440 = [resourcePaths stringByAppendingString: resourcePath];
443 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
451 /* If running as a self-contained app bundle, return as a path string
452 the filenames of the site-lisp, lisp and leim directories.
453 Ie, site-lisp:lisp:leim. Otherwise, return nil. */
455 NSBundle *bundle = [NSBundle mainBundle];
456 NSString *resourceDir = [bundle resourcePath];
457 NSString *resourcePath, *resourcePaths;
458 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
459 NSFileManager *fileManager = [NSFileManager defaultManager];
461 NSArray *paths = [resourceDir stringsByAppendingPaths:
462 [NSArray arrayWithObjects:
463 @"site-lisp", @"lisp", @"leim", nil]];
464 NSEnumerator *pathEnum = [paths objectEnumerator];
467 /* Hack to skip site-lisp. */
468 if (no_site_lisp) resourcePath = [pathEnum nextObject];
470 while ((resourcePath = [pathEnum nextObject]))
472 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
475 if ([resourcePaths length] > 0)
477 = [resourcePaths stringByAppendingString: pathSeparator];
479 = [resourcePaths stringByAppendingString: resourcePath];
482 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
488 ns_timeout (int usecs)
489 /* --------------------------------------------------------------------------
490 Blocking timer utility used by ns_ring_bell
491 -------------------------------------------------------------------------- */
493 struct timespec wakeup = timespec_add (current_timespec (),
494 make_timespec (0, usecs * 1000));
496 /* Keep waiting until past the time wakeup. */
499 struct timespec timeout, now = current_timespec ();
500 if (timespec_cmp (wakeup, now) <= 0)
502 timeout = timespec_sub (wakeup, now);
504 /* Try to wait that long--but we might wake up sooner. */
505 pselect (0, NULL, NULL, NULL, &timeout, NULL);
511 ns_release_object (void *obj)
512 /* --------------------------------------------------------------------------
513 Release an object (callable from C)
514 -------------------------------------------------------------------------- */
521 ns_retain_object (void *obj)
522 /* --------------------------------------------------------------------------
523 Retain an object (callable from C)
524 -------------------------------------------------------------------------- */
531 ns_alloc_autorelease_pool (void)
532 /* --------------------------------------------------------------------------
533 Allocate a pool for temporary objects (callable from C)
534 -------------------------------------------------------------------------- */
536 return [[NSAutoreleasePool alloc] init];
541 ns_release_autorelease_pool (void *pool)
542 /* --------------------------------------------------------------------------
543 Free a pool and temporary objects it refers to (callable from C)
544 -------------------------------------------------------------------------- */
546 ns_release_object (pool);
551 /* ==========================================================================
553 Focus (clipping) and screen update
555 ========================================================================== */
558 // Window constraining
559 // -------------------
561 // To ensure that the windows are not placed under the menu bar, they
562 // are typically moved by the call-back constrainFrameRect. However,
563 // by overriding it, it's possible to inhibit this, leaving the window
564 // in it's original position.
566 // It's possible to hide the menu bar. However, technically, it's only
567 // possible to hide it when the application is active. To ensure that
568 // this work properly, the menu bar and window constraining are
569 // deferred until the application becomes active.
571 // Even though it's not possible to manually move a window above the
572 // top of the screen, it is allowed if it's done programmatically,
573 // when the menu is hidden. This allows the editable area to cover the
574 // full screen height.
579 // Use the following extra files:
582 // ;; Hide menu and place frame slightly above the top of the screen.
583 // (setq ns-auto-hide-menu-bar t)
584 // (set-frame-position (selected-frame) 0 -20)
588 // emacs -Q -l init.el
590 // Result: No menu bar, and the title bar should be above the screen.
596 // Result: Menu bar visible, frame placed immediately below the menu.
600 ns_constrain_all_frames (void)
602 Lisp_Object tail, frame;
604 FOR_EACH_FRAME (tail, frame)
606 struct frame *f = XFRAME (frame);
609 NSView *view = FRAME_NS_VIEW (f);
610 /* This no-op will trigger the default window placing
611 * constraint system. */
612 f->output_data.ns->dont_constrain = 0;
613 [[view window] setFrameOrigin:[[view window] frame].origin];
619 /* True, if the menu bar should be hidden. */
622 ns_menu_bar_should_be_hidden (void)
624 return !NILP (ns_auto_hide_menu_bar)
625 && [NSApp respondsToSelector:@selector(setPresentationOptions:)];
629 /* Show or hide the menu bar, based on user setting. */
632 ns_update_auto_hide_menu_bar (void)
635 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
638 NSTRACE (ns_update_auto_hide_menu_bar);
642 && [NSApp respondsToSelector:@selector(setPresentationOptions:)])
644 // Note, "setPresentationOptions" triggers an error unless the
645 // application is active.
646 BOOL menu_bar_should_be_hidden = ns_menu_bar_should_be_hidden ();
648 if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden)
650 NSApplicationPresentationOptions options
651 = NSApplicationPresentationAutoHideDock;
653 if (menu_bar_should_be_hidden)
654 options |= NSApplicationPresentationAutoHideMenuBar;
656 [NSApp setPresentationOptions: options];
658 ns_menu_bar_is_hidden = menu_bar_should_be_hidden;
660 if (!ns_menu_bar_is_hidden)
662 ns_constrain_all_frames ();
674 ns_update_begin (struct frame *f)
675 /* --------------------------------------------------------------------------
676 Prepare for a grouped sequence of drawing calls
677 external (RIF) call; whole frame, called before update_window_begin
678 -------------------------------------------------------------------------- */
680 NSView *view = FRAME_NS_VIEW (f);
681 NSTRACE (ns_update_begin);
683 ns_update_auto_hide_menu_bar ();
685 ns_updating_frame = f;
688 /* drawRect may have been called for say the minibuffer, and then clip path
689 is for the minibuffer. But the display engine may draw more because
690 we have set the frame as garbaged. So reset clip path to the whole
695 NSRect r = [view frame];
696 NSRect cr = [[view window] frame];
697 /* If a large frame size is set, r may be larger than the window frame
698 before constrained. In that case don't change the clip path, as we
699 will clear in to the tool bar and title bar. */
701 + FRAME_NS_TITLEBAR_HEIGHT (f)
702 + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height)
704 bp = [[NSBezierPath bezierPathWithRect: r] retain];
711 #ifdef NS_IMPL_GNUSTEP
712 uRect = NSMakeRect (0, 0, 0, 0);
718 ns_update_window_begin (struct window *w)
719 /* --------------------------------------------------------------------------
720 Prepare for a grouped sequence of drawing calls
721 external (RIF) call; for one window, called after update_begin
722 -------------------------------------------------------------------------- */
724 struct frame *f = XFRAME (WINDOW_FRAME (w));
725 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
727 NSTRACE (ns_update_window_begin);
728 w->output_cursor = w->cursor;
732 if (f == hlinfo->mouse_face_mouse_frame)
734 /* Don't do highlighting for mouse motion during the update. */
735 hlinfo->mouse_face_defer = 1;
737 /* If the frame needs to be redrawn,
738 simply forget about any prior mouse highlighting. */
739 if (FRAME_GARBAGED_P (f))
740 hlinfo->mouse_face_window = Qnil;
742 /* (further code for mouse faces ifdef'd out in other terms elided) */
750 ns_update_window_end (struct window *w, bool cursor_on_p,
751 bool mouse_face_overwritten_p)
752 /* --------------------------------------------------------------------------
753 Finished a grouped sequence of drawing calls
754 external (RIF) call; for one window called before update_end
755 -------------------------------------------------------------------------- */
757 /* note: this fn is nearly identical in all terms */
758 if (!w->pseudo_window_p)
763 display_and_set_cursor (w, 1,
764 w->output_cursor.hpos, w->output_cursor.vpos,
765 w->output_cursor.x, w->output_cursor.y);
767 if (draw_window_fringes (w, 1))
768 x_draw_vertical_border (w);
773 /* If a row with mouse-face was overwritten, arrange for
774 frame_up_to_date to redisplay the mouse highlight. */
775 if (mouse_face_overwritten_p)
776 reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
778 NSTRACE (update_window_end);
783 ns_update_end (struct frame *f)
784 /* --------------------------------------------------------------------------
785 Finished a grouped sequence of drawing calls
786 external (RIF) call; for whole frame, called after update_window_end
787 -------------------------------------------------------------------------- */
789 EmacsView *view = FRAME_NS_VIEW (f);
791 /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
792 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
797 [[view window] flushWindow];
800 ns_updating_frame = NULL;
801 NSTRACE (ns_update_end);
805 ns_focus (struct frame *f, NSRect *r, int n)
806 /* --------------------------------------------------------------------------
807 Internal: Focus on given frame. During small local updates this is used to
808 draw, however during large updates, ns_update_begin and ns_update_end are
809 called to wrap the whole thing, in which case these calls are stubbed out.
810 Except, on GNUstep, we accumulate the rectangle being drawn into, because
811 the back end won't do this automatically, and will just end up flushing
813 -------------------------------------------------------------------------- */
815 // NSTRACE (ns_focus);
817 fprintf (stderr, "focus: %d", c++);
818 if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height);
819 fprintf (stderr, "\n"); */
821 if (f != ns_updating_frame)
823 NSView *view = FRAME_NS_VIEW (f);
824 if (view != focus_view)
826 if (focus_view != NULL)
828 [focus_view unlockFocus];
829 [[focus_view window] flushWindow];
836 /*if (view) debug_lock++; */
843 [[NSGraphicsContext currentContext] saveGraphicsState];
845 NSRectClipList (r, 2);
854 ns_unfocus (struct frame *f)
855 /* --------------------------------------------------------------------------
856 Internal: Remove focus on given frame
857 -------------------------------------------------------------------------- */
859 // NSTRACE (ns_unfocus);
863 [[NSGraphicsContext currentContext] restoreGraphicsState];
867 if (f != ns_updating_frame)
869 if (focus_view != NULL)
871 [focus_view unlockFocus];
872 [[focus_view window] flushWindow];
881 ns_clip_to_row (struct window *w, struct glyph_row *row,
882 enum glyph_row_area area, BOOL gc)
883 /* --------------------------------------------------------------------------
884 Internal (but parallels other terms): Focus drawing on given row
885 -------------------------------------------------------------------------- */
887 struct frame *f = XFRAME (WINDOW_FRAME (w));
889 int window_x, window_y, window_width;
891 window_box (w, area, &window_x, &window_y, &window_width, 0);
893 clip_rect.origin.x = window_x;
894 clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
895 clip_rect.origin.y = max (clip_rect.origin.y, window_y);
896 clip_rect.size.width = window_width;
897 clip_rect.size.height = row->visible_height;
899 ns_focus (f, &clip_rect, 1);
904 ns_ring_bell (struct frame *f)
905 /* --------------------------------------------------------------------------
907 -------------------------------------------------------------------------- */
909 NSTRACE (ns_ring_bell);
912 NSAutoreleasePool *pool;
913 struct frame *frame = SELECTED_FRAME ();
917 pool = [[NSAutoreleasePool alloc] init];
919 view = FRAME_NS_VIEW (frame);
923 NSPoint dim = NSMakePoint (128, 128);
926 r.origin.x += (r.size.width - dim.x) / 2;
927 r.origin.y += (r.size.height - dim.y) / 2;
928 r.size.width = dim.x;
929 r.size.height = dim.y;
930 surr = NSInsetRect (r, -2, -2);
931 ns_focus (frame, &surr, 1);
932 [[view window] cacheImageInRect: [view convertRect: surr toView:nil]];
933 [ns_lookup_indexed_color (NS_FACE_FOREGROUND
934 (FRAME_DEFAULT_FACE (frame)), frame) set];
936 [[view window] flushWindow];
938 [[view window] restoreCachedImage];
939 [[view window] flushWindow];
951 /* ==========================================================================
953 Frame / window manager related functions
955 ========================================================================== */
959 ns_raise_frame (struct frame *f)
960 /* --------------------------------------------------------------------------
961 Bring window to foreground and make it active
962 -------------------------------------------------------------------------- */
965 check_window_system (f);
966 view = FRAME_NS_VIEW (f);
968 if (FRAME_VISIBLE_P (f))
969 [[view window] makeKeyAndOrderFront: NSApp];
975 ns_lower_frame (struct frame *f)
976 /* --------------------------------------------------------------------------
978 -------------------------------------------------------------------------- */
981 check_window_system (f);
982 view = FRAME_NS_VIEW (f);
984 [[view window] orderBack: NSApp];
990 ns_frame_raise_lower (struct frame *f, int raise)
991 /* --------------------------------------------------------------------------
993 -------------------------------------------------------------------------- */
995 NSTRACE (ns_frame_raise_lower);
1005 ns_frame_rehighlight (struct frame *frame)
1006 /* --------------------------------------------------------------------------
1007 External (hook): called on things like window switching within frame
1008 -------------------------------------------------------------------------- */
1010 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
1011 struct frame *old_highlight = dpyinfo->x_highlight_frame;
1013 NSTRACE (ns_frame_rehighlight);
1014 if (dpyinfo->x_focus_frame)
1016 dpyinfo->x_highlight_frame
1017 = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1018 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1019 : dpyinfo->x_focus_frame);
1020 if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame))
1022 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
1023 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
1027 dpyinfo->x_highlight_frame = 0;
1029 if (dpyinfo->x_highlight_frame &&
1030 dpyinfo->x_highlight_frame != old_highlight)
1034 x_update_cursor (old_highlight, 1);
1035 x_set_frame_alpha (old_highlight);
1037 if (dpyinfo->x_highlight_frame)
1039 x_update_cursor (dpyinfo->x_highlight_frame, 1);
1040 x_set_frame_alpha (dpyinfo->x_highlight_frame);
1047 x_make_frame_visible (struct frame *f)
1048 /* --------------------------------------------------------------------------
1049 External: Show the window (X11 semantics)
1050 -------------------------------------------------------------------------- */
1052 NSTRACE (x_make_frame_visible);
1053 /* XXX: at some points in past this was not needed, as the only place that
1054 called this (frame.c:Fraise_frame ()) also called raise_lower;
1055 if this ends up the case again, comment this out again. */
1056 if (!FRAME_VISIBLE_P (f))
1058 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1060 SET_FRAME_VISIBLE (f, 1);
1063 /* Making a new frame from a fullscreen frame will make the new frame
1064 fullscreen also. So skip handleFS as this will print an error. */
1065 if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH
1066 && [view isFullscreen])
1069 if (f->want_fullscreen != FULLSCREEN_NONE)
1080 x_make_frame_invisible (struct frame *f)
1081 /* --------------------------------------------------------------------------
1082 External: Hide the window (X11 semantics)
1083 -------------------------------------------------------------------------- */
1086 NSTRACE (x_make_frame_invisible);
1087 check_window_system (f);
1088 view = FRAME_NS_VIEW (f);
1089 [[view window] orderOut: NSApp];
1090 SET_FRAME_VISIBLE (f, 0);
1091 SET_FRAME_ICONIFIED (f, 0);
1096 x_iconify_frame (struct frame *f)
1097 /* --------------------------------------------------------------------------
1098 External: Iconify window
1099 -------------------------------------------------------------------------- */
1102 struct ns_display_info *dpyinfo;
1104 NSTRACE (x_iconify_frame);
1105 check_window_system (f);
1106 view = FRAME_NS_VIEW (f);
1107 dpyinfo = FRAME_DISPLAY_INFO (f);
1109 if (dpyinfo->x_highlight_frame == f)
1110 dpyinfo->x_highlight_frame = 0;
1112 if ([[view window] windowNumber] <= 0)
1114 /* the window is still deferred. Make it very small, bring it
1115 on screen and order it out. */
1116 NSRect s = { { 100, 100}, {0, 0} };
1118 t = [[view window] frame];
1119 [[view window] setFrame: s display: NO];
1120 [[view window] orderBack: NSApp];
1121 [[view window] orderOut: NSApp];
1122 [[view window] setFrame: t display: NO];
1124 [[view window] miniaturize: NSApp];
1127 /* Free X resources of frame F. */
1130 x_free_frame_resources (struct frame *f)
1133 struct ns_display_info *dpyinfo;
1134 Mouse_HLInfo *hlinfo;
1136 NSTRACE (x_free_frame_resources);
1137 check_window_system (f);
1138 view = FRAME_NS_VIEW (f);
1139 dpyinfo = FRAME_DISPLAY_INFO (f);
1140 hlinfo = MOUSE_HL_INFO (f);
1142 [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
1146 free_frame_menubar (f);
1148 if (FRAME_FACE_CACHE (f))
1149 free_frame_faces (f);
1151 if (f == dpyinfo->x_focus_frame)
1152 dpyinfo->x_focus_frame = 0;
1153 if (f == dpyinfo->x_highlight_frame)
1154 dpyinfo->x_highlight_frame = 0;
1155 if (f == hlinfo->mouse_face_mouse_frame)
1156 reset_mouse_highlight (hlinfo);
1158 if (f->output_data.ns->miniimage != nil)
1159 [f->output_data.ns->miniimage release];
1161 [[view window] close];
1164 xfree (f->output_data.ns);
1170 x_destroy_window (struct frame *f)
1171 /* --------------------------------------------------------------------------
1172 External: Delete the window
1173 -------------------------------------------------------------------------- */
1175 NSTRACE (x_destroy_window);
1176 check_window_system (f);
1177 x_free_frame_resources (f);
1183 x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1184 /* --------------------------------------------------------------------------
1185 External: Position the window
1186 -------------------------------------------------------------------------- */
1188 NSView *view = FRAME_NS_VIEW (f);
1189 NSArray *screens = [NSScreen screens];
1190 NSScreen *fscreen = [screens objectAtIndex: 0];
1191 NSScreen *screen = [[view window] screen];
1193 NSTRACE (x_set_offset);
1200 if (view != nil && screen && fscreen)
1202 f->left_pos = f->size_hint_flags & XNegative
1203 ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
1205 /* We use visibleFrame here to take menu bar into account.
1206 Ideally we should also adjust left/top with visibleFrame.origin. */
1208 f->top_pos = f->size_hint_flags & YNegative
1209 ? ([screen visibleFrame].size.height + f->top_pos
1210 - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
1211 - FRAME_TOOLBAR_HEIGHT (f))
1213 #ifdef NS_IMPL_GNUSTEP
1214 if (f->left_pos < 100)
1215 f->left_pos = 100; /* don't overlap menu */
1217 /* Constrain the setFrameTopLeftPoint so we don't move behind the
1219 f->output_data.ns->dont_constrain = 0;
1220 [[view window] setFrameTopLeftPoint:
1221 NSMakePoint (SCREENMAXBOUND (f->left_pos),
1222 SCREENMAXBOUND ([fscreen frame].size.height
1223 - NS_TOP_POS (f)))];
1224 f->size_hint_flags &= ~(XNegative|YNegative);
1232 x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
1233 /* --------------------------------------------------------------------------
1234 Adjust window pixel size based on given character grid size
1235 Impl is a bit more complex than other terms, need to do some
1237 -------------------------------------------------------------------------- */
1239 EmacsView *view = FRAME_NS_VIEW (f);
1240 NSWindow *window = [view window];
1241 NSRect wr = [window frame];
1242 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1243 int pixelwidth, pixelheight;
1245 NSTRACE (x_set_window_size);
1250 /*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
1254 check_frame_size (f, &rows, &cols);
1256 f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
1257 compute_fringe_widths (f, 0);
1259 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
1260 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1262 /* If we have a toolbar, take its height into account. */
1263 if (tb && ! [view isFullscreen])
1265 /* NOTE: previously this would generate wrong result if toolbar not
1266 yet displayed and fixing toolbar_height=32 helped, but
1267 now (200903) seems no longer needed */
1268 FRAME_TOOLBAR_HEIGHT (f) =
1269 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1270 - FRAME_NS_TITLEBAR_HEIGHT (f);
1271 #ifdef NS_IMPL_GNUSTEP
1272 FRAME_TOOLBAR_HEIGHT (f) -= 3;
1276 FRAME_TOOLBAR_HEIGHT (f) = 0;
1278 wr.size.width = pixelwidth + f->border_width;
1279 wr.size.height = pixelheight;
1280 if (! [view isFullscreen])
1281 wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f)
1282 + FRAME_TOOLBAR_HEIGHT (f);
1284 /* Do not try to constrain to this screen. We may have multiple
1285 screens, and want Emacs to span those. Constraining to screen
1286 prevents that, and that is not nice to the user. */
1287 if (f->output_data.ns->zooming)
1288 f->output_data.ns->zooming = 0;
1290 wr.origin.y += FRAME_PIXEL_HEIGHT (f) - pixelheight;
1292 [view setRows: rows andColumns: cols];
1293 [window setFrame: wr display: YES];
1295 /*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */
1297 /* This is a trick to compensate for Emacs' managing the scrollbar area
1298 as a fixed number of standard character columns. Instead of leaving
1299 blank space for the extra, we chopped it off above. Now for
1300 left-hand scrollbars, we shift all rendering to the left by the
1301 difference between the real width and Emacs' imagined one. For
1302 right-hand bars, don't worry about it since the extra is never used.
1303 (Obviously doesn't work for vertically split windows tho..) */
1305 NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
1306 ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
1307 - NS_SCROLL_BAR_WIDTH (f), 0)
1308 : NSMakePoint (0, 0);
1309 [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
1310 [view setBoundsOrigin: origin];
1313 change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
1314 FRAME_PIXEL_WIDTH (f) = pixelwidth;
1315 FRAME_PIXEL_HEIGHT (f) = pixelheight;
1316 /* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
1318 mark_window_cursors_off (XWINDOW (f->root_window));
1319 cancel_mouse_face (f);
1326 ns_fullscreen_hook (struct frame *f)
1328 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1330 if (!FRAME_VISIBLE_P (f))
1333 if (! [view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH)
1335 /* Old style fs don't initiate correctly if created from
1336 init/default-frame alist, so use a timer (not nice...).
1338 [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view
1339 selector: @selector (handleFS)
1340 userInfo: nil repeats: NO];
1349 /* ==========================================================================
1353 ========================================================================== */
1357 ns_lookup_indexed_color (unsigned long idx, struct frame *f)
1359 struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
1360 if (idx < 1 || idx >= color_table->avail)
1362 return color_table->colors[idx];
1367 ns_index_color (NSColor *color, struct frame *f)
1369 struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
1373 if (!color_table->colors)
1375 color_table->size = NS_COLOR_CAPACITY;
1376 color_table->avail = 1; /* skip idx=0 as marker */
1377 color_table->colors = xmalloc (color_table->size * sizeof (NSColor *));
1378 color_table->colors[0] = nil;
1379 color_table->empty_indices = [[NSMutableSet alloc] init];
1382 /* do we already have this color ? */
1383 for (i = 1; i < color_table->avail; i++)
1384 if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
1387 if ([color_table->empty_indices count] > 0)
1389 NSNumber *index = [color_table->empty_indices anyObject];
1390 [color_table->empty_indices removeObject: index];
1391 idx = [index unsignedLongValue];
1395 if (color_table->avail == color_table->size)
1396 color_table->colors =
1397 xpalloc (color_table->colors, &color_table->size, 1,
1398 min (ULONG_MAX, PTRDIFF_MAX), sizeof *color_table->colors);
1399 idx = color_table->avail++;
1402 color_table->colors[idx] = color;
1404 /*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1410 ns_free_indexed_color (unsigned long idx, struct frame *f)
1412 struct ns_color_table *color_table;
1419 color_table = FRAME_DISPLAY_INFO (f)->color_table;
1421 if (idx <= 0 || idx >= color_table->size) {
1422 message1 ("ns_free_indexed_color: Color index out of range.\n");
1426 index = [NSNumber numberWithUnsignedInt: idx];
1427 if ([color_table->empty_indices containsObject: index]) {
1428 message1 ("ns_free_indexed_color: attempt to free already freed color.\n");
1432 color = color_table->colors[idx];
1434 color_table->colors[idx] = nil;
1435 [color_table->empty_indices addObject: index];
1436 /*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1441 ns_get_color (const char *name, NSColor **col)
1442 /* --------------------------------------------------------------------------
1444 -------------------------------------------------------------------------- */
1445 /* On *Step, we attempt to mimic the X11 platform here, down to installing an
1446 X11 rgb.txt-compatible color list in Emacs.clr (see ns_term_init()).
1447 See: http://thread.gmane.org/gmane.emacs.devel/113050/focus=113272). */
1450 static char hex[20];
1452 float r = -1.0, g, b;
1453 NSString *nsname = [NSString stringWithUTF8String: name];
1455 /*fprintf (stderr, "ns_get_color: '%s'\n", name); */
1458 if ([nsname isEqualToString: @"ns_selection_color"])
1460 nsname = ns_selection_color;
1461 name = [ns_selection_color UTF8String];
1464 /* First, check for some sort of numeric specification. */
1467 if (name[0] == '0' || name[0] == '1' || name[0] == '.') /* RGB decimal */
1469 NSScanner *scanner = [NSScanner scannerWithString: nsname];
1470 [scanner scanFloat: &r];
1471 [scanner scanFloat: &g];
1472 [scanner scanFloat: &b];
1474 else if (!strncmp(name, "rgb:", 4)) /* A newer X11 format -- rgb:r/g/b */
1475 scaling = (snprintf (hex, sizeof hex, "%s", name + 4) - 2) / 3;
1476 else if (name[0] == '#') /* An old X11 format; convert to newer */
1478 int len = (strlen(name) - 1);
1479 int start = (len % 3 == 0) ? 1 : len / 4 + 1;
1481 scaling = strlen(name+start) / 3;
1482 for (i = 0; i < 3; i++)
1483 sprintf (hex + i * (scaling + 1), "%.*s/", scaling,
1484 name + start + i * scaling);
1485 hex[3 * (scaling + 1) - 1] = '\0';
1491 float fscale = scaling == 4 ? 65535.0 : (scaling == 2 ? 255.0 : 15.0);
1492 if (sscanf (hex, "%x/%x/%x", &rr, &gg, &bb))
1502 *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0];
1507 /* Otherwise, color is expected to be from a list */
1509 NSEnumerator *lenum, *cenum;
1513 #ifdef NS_IMPL_GNUSTEP
1514 /* XXX: who is wrong, the requestor or the implementation? */
1515 if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
1517 nsname = @"highlightColor";
1520 lenum = [[NSColorList availableColorLists] objectEnumerator];
1521 while ( (clist = [lenum nextObject]) && new == nil)
1523 cenum = [[clist allKeys] objectEnumerator];
1524 while ( (name = [cenum nextObject]) && new == nil )
1526 if ([name compare: nsname
1527 options: NSCaseInsensitiveSearch] == NSOrderedSame )
1528 new = [clist colorWithKey: name];
1534 *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
1541 ns_lisp_to_color (Lisp_Object color, NSColor **col)
1542 /* --------------------------------------------------------------------------
1543 Convert a Lisp string object to a NS color
1544 -------------------------------------------------------------------------- */
1546 NSTRACE (ns_lisp_to_color);
1547 if (STRINGP (color))
1548 return ns_get_color (SSDATA (color), col);
1549 else if (SYMBOLP (color))
1550 return ns_get_color (SSDATA (SYMBOL_NAME (color)), col);
1556 ns_color_to_lisp (NSColor *col)
1557 /* --------------------------------------------------------------------------
1558 Convert a color to a lisp string with the RGB equivalent
1559 -------------------------------------------------------------------------- */
1561 EmacsCGFloat red, green, blue, alpha, gray;
1564 NSTRACE (ns_color_to_lisp);
1567 if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
1569 if ((str =[[col colorNameComponent] UTF8String]))
1572 return build_string ((char *)str);
1575 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
1576 getRed: &red green: &green blue: &blue alpha: &alpha];
1577 if (red ==green && red ==blue)
1579 [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
1580 getWhite: &gray alpha: &alpha];
1581 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1582 lrint (gray * 0xff), lrint (gray * 0xff), lrint (gray * 0xff));
1584 return build_string (buf);
1587 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1588 lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
1591 return build_string (buf);
1596 ns_query_color(void *col, XColor *color_def, int setPixel)
1597 /* --------------------------------------------------------------------------
1598 Get ARGB values out of NSColor col and put them into color_def.
1599 If setPixel, set the pixel to a concatenated version.
1600 and set color_def pixel to the resulting index.
1601 -------------------------------------------------------------------------- */
1603 EmacsCGFloat r, g, b, a;
1605 [((NSColor *)col) getRed: &r green: &g blue: &b alpha: &a];
1606 color_def->red = r * 65535;
1607 color_def->green = g * 65535;
1608 color_def->blue = b * 65535;
1610 if (setPixel == YES)
1612 = ARGB_TO_ULONG((int)(a*255),
1613 (int)(r*255), (int)(g*255), (int)(b*255));
1618 ns_defined_color (struct frame *f,
1623 /* --------------------------------------------------------------------------
1624 Return true if named color found, and set color_def rgb accordingly.
1625 If makeIndex and alloc are nonzero put the color in the color_table,
1626 and set color_def pixel to the resulting index.
1627 If makeIndex is zero, set color_def pixel to ARGB.
1628 Return false if not found
1629 -------------------------------------------------------------------------- */
1632 NSTRACE (ns_defined_color);
1635 if (ns_get_color (name, &col) != 0) /* Color not found */
1640 if (makeIndex && alloc)
1641 color_def->pixel = ns_index_color (col, f);
1642 ns_query_color (col, color_def, !makeIndex);
1649 x_set_frame_alpha (struct frame *f)
1650 /* --------------------------------------------------------------------------
1651 change the entire-frame transparency
1652 -------------------------------------------------------------------------- */
1654 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1656 double alpha_min = 1.0;
1658 if (dpyinfo->x_highlight_frame == f)
1659 alpha = f->alpha[0];
1661 alpha = f->alpha[1];
1663 if (FLOATP (Vframe_alpha_lower_limit))
1664 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
1665 else if (INTEGERP (Vframe_alpha_lower_limit))
1666 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
1670 else if (1.0 < alpha)
1672 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
1675 #ifdef NS_IMPL_COCOA
1677 EmacsView *view = FRAME_NS_VIEW (f);
1678 [[view window] setAlphaValue: alpha];
1684 /* ==========================================================================
1688 ========================================================================== */
1692 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
1693 /* --------------------------------------------------------------------------
1694 Programmatically reposition mouse pointer in pixel coordinates
1695 -------------------------------------------------------------------------- */
1697 NSTRACE (x_set_mouse_pixel_position);
1700 /* FIXME: this does not work, and what about GNUstep? */
1701 #ifdef NS_IMPL_COCOA
1702 [FRAME_NS_VIEW (f) lockFocus];
1703 PSsetmouse ((float)pix_x, (float)pix_y);
1704 [FRAME_NS_VIEW (f) unlockFocus];
1711 x_set_mouse_position (struct frame *f, int h, int v)
1712 /* --------------------------------------------------------------------------
1713 Programmatically reposition mouse pointer in character coordinates
1714 -------------------------------------------------------------------------- */
1718 pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2;
1719 pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2;
1721 if (pix_x < 0) pix_x = 0;
1722 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
1724 if (pix_y < 0) pix_y = 0;
1725 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
1727 x_set_mouse_pixel_position (f, pix_x, pix_y);
1732 note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y)
1733 /* ------------------------------------------------------------------------
1734 Called by EmacsView on mouseMovement events. Passes on
1735 to emacs mainstream code if we moved off of a rect of interest
1736 known as last_mouse_glyph.
1737 ------------------------------------------------------------------------ */
1739 // NSTRACE (note_mouse_movement);
1741 XSETFRAME (last_mouse_motion_frame, frame);
1743 /* Note, this doesn't get called for enter/leave, since we don't have a
1744 position. Those are taken care of in the corresponding NSView methods. */
1746 /* has movement gone beyond last rect we were tracking? */
1747 if (x < last_mouse_glyph.origin.x ||
1748 x >= (last_mouse_glyph.origin.x + last_mouse_glyph.size.width) ||
1749 y < last_mouse_glyph.origin.y ||
1750 y >= (last_mouse_glyph.origin.y + last_mouse_glyph.size.height))
1752 ns_update_begin(frame);
1753 frame->mouse_moved = 1;
1754 note_mouse_highlight (frame, x, y);
1755 remember_mouse_glyph (frame, x, y, &last_mouse_glyph);
1756 ns_update_end(frame);
1765 ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
1766 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
1768 /* --------------------------------------------------------------------------
1769 External (hook): inform emacs about mouse position and hit parts.
1770 If a scrollbar is being dragged, set bar_window, part, x, y, time.
1771 x & y should be position in the scrollbar (the whole bar, not the handle)
1772 and length of scrollbar respectively
1773 -------------------------------------------------------------------------- */
1777 Lisp_Object frame, tail;
1779 struct ns_display_info *dpyinfo;
1781 NSTRACE (ns_mouse_position);
1785 fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n");
1789 dpyinfo = FRAME_DISPLAY_INFO (*fp);
1793 if (last_mouse_scroll_bar != nil && insist == 0)
1795 /* TODO: we do not use this path at the moment because drag events will
1796 go directly to the EmacsScroller. Leaving code in for now. */
1797 [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window
1799 if (time) *time = last_mouse_movement_time;
1800 last_mouse_scroll_bar = nil;
1804 /* Clear the mouse-moved flag for every frame on this display. */
1805 FOR_EACH_FRAME (tail, frame)
1806 if (FRAME_NS_P (XFRAME (frame))
1807 && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
1808 XFRAME (frame)->mouse_moved = 0;
1810 last_mouse_scroll_bar = nil;
1811 if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame))
1812 f = last_mouse_frame;
1814 f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame
1815 : SELECTED_FRAME ();
1817 if (f && FRAME_NS_P (f))
1819 view = FRAME_NS_VIEW (*fp);
1821 position = [[view window] mouseLocationOutsideOfEventStream];
1822 position = [view convertPoint: position fromView: nil];
1823 remember_mouse_glyph (f, position.x, position.y, &last_mouse_glyph);
1824 /*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
1826 if (bar_window) *bar_window = Qnil;
1827 if (part) *part = 0; /*scroll_bar_handle; */
1829 if (x) XSETINT (*x, lrint (position.x));
1830 if (y) XSETINT (*y, lrint (position.y));
1831 if (time) *time = last_mouse_movement_time;
1841 ns_frame_up_to_date (struct frame *f)
1842 /* --------------------------------------------------------------------------
1843 External (hook): Fix up mouse highlighting right after a full update.
1844 Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls.
1845 -------------------------------------------------------------------------- */
1847 NSTRACE (ns_frame_up_to_date);
1851 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
1852 if (f == hlinfo->mouse_face_mouse_frame)
1856 note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
1857 hlinfo->mouse_face_mouse_x,
1858 hlinfo->mouse_face_mouse_y);
1867 ns_define_frame_cursor (struct frame *f, Cursor cursor)
1868 /* --------------------------------------------------------------------------
1869 External (RIF): set frame mouse pointer type.
1870 -------------------------------------------------------------------------- */
1872 NSTRACE (ns_define_frame_cursor);
1873 if (FRAME_POINTER_TYPE (f) != cursor)
1875 EmacsView *view = FRAME_NS_VIEW (f);
1876 FRAME_POINTER_TYPE (f) = cursor;
1877 [[view window] invalidateCursorRectsForView: view];
1878 /* Redisplay assumes this function also draws the changed frame
1879 cursor, but this function doesn't, so do it explicitly. */
1880 x_update_cursor (f, 1);
1886 /* ==========================================================================
1890 ========================================================================== */
1894 ns_convert_key (unsigned code)
1895 /* --------------------------------------------------------------------------
1896 Internal call used by NSView-keyDown.
1897 -------------------------------------------------------------------------- */
1899 const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym)
1900 / sizeof (convert_ns_to_X_keysym[0]));
1902 /* An array would be faster, but less easy to read. */
1903 for (keysym = 0; keysym < last_keysym; keysym += 2)
1904 if (code == convert_ns_to_X_keysym[keysym])
1905 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
1907 /* if decide to use keyCode and Carbon table, use this line:
1908 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
1913 x_get_keysym_name (int keysym)
1914 /* --------------------------------------------------------------------------
1915 Called by keyboard.c. Not sure if the return val is important, except
1917 -------------------------------------------------------------------------- */
1919 static char value[16];
1920 NSTRACE (x_get_keysym_name);
1921 sprintf (value, "%d", keysym);
1927 /* ==========================================================================
1929 Block drawing operations
1931 ========================================================================== */
1935 ns_redraw_scroll_bars (struct frame *f)
1939 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
1940 NSTRACE (ns_redraw_scroll_bars);
1941 for (i =[subviews count]-1; i >= 0; i--)
1943 view = [subviews objectAtIndex: i];
1944 if (![view isKindOfClass: [EmacsScroller class]]) continue;
1951 ns_clear_frame (struct frame *f)
1952 /* --------------------------------------------------------------------------
1953 External (hook): Erase the entire frame
1954 -------------------------------------------------------------------------- */
1956 NSView *view = FRAME_NS_VIEW (f);
1959 NSTRACE (ns_clear_frame);
1961 /* comes on initial frame because we have
1962 after-make-frame-functions = select-frame */
1963 if (!FRAME_DEFAULT_FACE (f))
1966 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
1971 ns_focus (f, &r, 1);
1972 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
1976 /* as of 2006/11 or so this is now needed */
1977 ns_redraw_scroll_bars (f);
1983 ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
1984 /* --------------------------------------------------------------------------
1985 External (RIF): Clear section of frame
1986 -------------------------------------------------------------------------- */
1988 NSRect r = NSMakeRect (x, y, width, height);
1989 NSView *view = FRAME_NS_VIEW (f);
1990 struct face *face = FRAME_DEFAULT_FACE (f);
1995 NSTRACE (ns_clear_frame_area);
1997 r = NSIntersectionRect (r, [view frame]);
1998 ns_focus (f, &r, 1);
1999 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
2009 ns_scroll_run (struct window *w, struct run *run)
2010 /* --------------------------------------------------------------------------
2011 External (RIF): Insert or delete n lines at line vpos
2012 -------------------------------------------------------------------------- */
2014 struct frame *f = XFRAME (w->frame);
2015 int x, y, width, height, from_y, to_y, bottom_y;
2017 NSTRACE (ns_scroll_run);
2019 /* begin copy from other terms */
2020 /* Get frame-relative bounding box of the text display area of W,
2021 without mode lines. Include in this box the left and right
2023 window_box (w, ANY_AREA, &x, &y, &width, &height);
2025 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2026 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2027 bottom_y = y + height;
2031 /* Scrolling up. Make sure we don't copy part of the mode
2032 line at the bottom. */
2033 if (from_y + run->height > bottom_y)
2034 height = bottom_y - from_y;
2036 height = run->height;
2040 /* Scrolling down. Make sure we don't copy over the mode line.
2042 if (to_y + run->height > bottom_y)
2043 height = bottom_y - to_y;
2045 height = run->height;
2047 /* end copy from other terms */
2057 NSRect srcRect = NSMakeRect (x, from_y, width, height);
2058 NSRect dstRect = NSMakeRect (x, to_y, width, height);
2059 NSPoint dstOrigin = NSMakePoint (x, to_y);
2061 ns_focus (f, &dstRect, 1);
2062 NSCopyBits (0, srcRect , dstOrigin);
2071 ns_after_update_window_line (struct window *w, struct glyph_row *desired_row)
2072 /* --------------------------------------------------------------------------
2073 External (RIF): preparatory to fringe update after text was updated
2074 -------------------------------------------------------------------------- */
2079 NSTRACE (ns_after_update_window_line);
2081 /* begin copy from other terms */
2084 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2085 desired_row->redraw_fringe_bitmaps_p = 1;
2087 /* When a window has disappeared, make sure that no rest of
2088 full-width rows stays visible in the internal border. */
2089 if (windows_or_buffers_changed
2090 && desired_row->full_width_p
2091 && (f = XFRAME (w->frame),
2092 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2094 && (height = desired_row->visible_height,
2097 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2100 ns_clear_frame_area (f, 0, y, width, height);
2101 ns_clear_frame_area (f,
2102 FRAME_PIXEL_WIDTH (f) - width,
2110 ns_shift_glyphs_for_insert (struct frame *f,
2111 int x, int y, int width, int height,
2113 /* --------------------------------------------------------------------------
2114 External (RIF): copy an area horizontally, don't worry about clearing src
2115 -------------------------------------------------------------------------- */
2117 NSRect srcRect = NSMakeRect (x, y, width, height);
2118 NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
2119 NSPoint dstOrigin = dstRect.origin;
2121 NSTRACE (ns_shift_glyphs_for_insert);
2123 ns_focus (f, &dstRect, 1);
2124 NSCopyBits (0, srcRect, dstOrigin);
2130 /* ==========================================================================
2132 Character encoding and metrics
2134 ========================================================================== */
2138 ns_compute_glyph_string_overhangs (struct glyph_string *s)
2139 /* --------------------------------------------------------------------------
2140 External (RIF); compute left/right overhang of whole string and set in s
2141 -------------------------------------------------------------------------- */
2143 struct font *font = s->font;
2147 struct font_metrics metrics;
2148 unsigned int codes[2];
2149 codes[0] = *(s->char2b);
2150 codes[1] = *(s->char2b + s->nchars - 1);
2152 font->driver->text_extents (font, codes, 2, &metrics);
2153 s->left_overhang = -metrics.lbearing;
2155 = metrics.rbearing > metrics.width
2156 ? metrics.rbearing - metrics.width : 0;
2160 s->left_overhang = 0;
2161 s->right_overhang = ((struct nsfont_info *)font)->ital ?
2162 FONT_HEIGHT (font) * 0.2 : 0;
2168 /* ==========================================================================
2170 Fringe and cursor drawing
2172 ========================================================================== */
2175 extern int max_used_fringe_bitmap;
2177 ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2178 struct draw_fringe_bitmap_params *p)
2179 /* --------------------------------------------------------------------------
2180 External (RIF); fringe-related
2181 -------------------------------------------------------------------------- */
2183 struct frame *f = XFRAME (WINDOW_FRAME (w));
2184 struct face *face = p->face;
2185 static EmacsImage **bimgs = NULL;
2186 static int nBimgs = 0;
2188 /* grow bimgs if needed */
2189 if (nBimgs < max_used_fringe_bitmap)
2191 bimgs = xrealloc (bimgs, max_used_fringe_bitmap * sizeof *bimgs);
2192 memset (bimgs + nBimgs, 0,
2193 (max_used_fringe_bitmap - nBimgs) * sizeof *bimgs);
2194 nBimgs = max_used_fringe_bitmap;
2197 /* Must clip because of partially visible lines. */
2198 ns_clip_to_row (w, row, ANY_AREA, YES);
2202 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2204 /* If the fringe is adjacent to the left (right) scroll bar of a
2205 leftmost (rightmost, respectively) window, then extend its
2206 background to the gap between the fringe and the bar. */
2207 if ((WINDOW_LEFTMOST_P (w)
2208 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2209 || (WINDOW_RIGHTMOST_P (w)
2210 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2212 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2216 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
2217 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2218 * FRAME_COLUMN_WIDTH (f));
2222 /* Bitmap fills the fringe. */
2223 if (bar_area_x + bar_area_width == p->x)
2224 bx = bar_area_x + sb_width;
2225 else if (p->x + p->wd == bar_area_x)
2229 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2231 nx = bar_area_width - sb_width;
2232 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2234 ny = row->visible_height;
2239 if (bar_area_x + bar_area_width == bx)
2241 bx = bar_area_x + sb_width;
2242 nx += bar_area_width - sb_width;
2244 else if (bx + nx == bar_area_x)
2245 nx += bar_area_width - sb_width;
2250 if (bx >= 0 && nx > 0)
2252 NSRect r = NSMakeRect (bx, by, nx, ny);
2254 [ns_lookup_indexed_color (face->background, f) set];
2261 NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h);
2262 EmacsImage *img = bimgs[p->which - 1];
2266 unsigned short *bits = p->bits + p->dh;
2269 unsigned char *cbits = xmalloc (len);
2271 for (i = 0; i < len; i++)
2272 cbits[i] = ~(bits[i] & 0xff);
2273 img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
2275 bimgs[p->which - 1] = img;
2280 /* Since we composite the bitmap instead of just blitting it, we need
2281 to erase the whole background. */
2282 [ns_lookup_indexed_color(face->background, f) set];
2284 [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)];
2285 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
2287 fromRect: NSZeroRect
2288 operation: NSCompositeSourceOver
2294 NSPoint pt = r.origin;
2296 [img compositeToPoint: pt operation: NSCompositeSourceOver];
2305 ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2306 int x, int y, enum text_cursor_kinds cursor_type,
2307 int cursor_width, bool on_p, bool active_p)
2308 /* --------------------------------------------------------------------------
2309 External call (RIF): draw cursor.
2310 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
2311 -------------------------------------------------------------------------- */
2314 int fx, fy, h, cursor_height;
2315 struct frame *f = WINDOW_XFRAME (w);
2316 struct glyph *phys_cursor_glyph;
2317 struct glyph *cursor_glyph;
2319 NSColor *hollow_color = FRAME_BACKGROUND_COLOR (f);
2321 /* If cursor is out of bounds, don't draw garbage. This can happen
2322 in mini-buffer windows when switching between echo area glyphs
2325 NSTRACE (dumpcursor);
2330 w->phys_cursor_type = cursor_type;
2331 w->phys_cursor_on_p = on_p;
2333 if (cursor_type == NO_CURSOR)
2335 w->phys_cursor_width = 0;
2339 if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
2341 if (glyph_row->exact_window_width_line_p
2342 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
2344 glyph_row->cursor_in_fringe_p = 1;
2345 draw_fringe_bitmap (w, glyph_row, 0);
2350 /* We draw the cursor (with NSRectFill), then draw the glyph on top
2351 (other terminals do it the other way round). We must set
2352 w->phys_cursor_width to the cursor width. For bar cursors, that
2353 is CURSOR_WIDTH; for box cursors, it is the glyph width. */
2354 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
2356 /* The above get_phys_cursor_geometry call set w->phys_cursor_width
2357 to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */
2358 if (cursor_type == BAR_CURSOR)
2360 if (cursor_width < 1)
2361 cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
2362 w->phys_cursor_width = cursor_width;
2364 /* If we have an HBAR, "cursor_width" MAY specify height. */
2365 else if (cursor_type == HBAR_CURSOR)
2367 cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
2368 fy += h - cursor_height;
2372 r.origin.x = fx, r.origin.y = fy;
2374 r.size.width = w->phys_cursor_width;
2376 /* TODO: only needed in rare cases with last-resort font in HELLO..
2377 should we do this more efficiently? */
2378 ns_clip_to_row (w, glyph_row, ANY_AREA, NO); /* do ns_focus(f, &r, 1); if remove */
2381 face = FACE_FROM_ID (f, phys_cursor_glyph->face_id);
2382 if (face && NS_FACE_BACKGROUND (face)
2383 == ns_index_color (FRAME_CURSOR_COLOR (f), f))
2385 [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
2386 hollow_color = FRAME_CURSOR_COLOR (f);
2389 [FRAME_CURSOR_COLOR (f) set];
2391 #ifdef NS_IMPL_COCOA
2392 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
2393 atomic. Cleaner ways of doing this should be investigated.
2394 One way would be to set a global variable DRAWING_CURSOR
2395 when making the call to draw_phys..(), don't focus in that
2396 case, then move the ns_unfocus() here after that call. */
2397 NSDisableScreenUpdates ();
2400 switch (cursor_type)
2404 case FILLED_BOX_CURSOR:
2407 case HOLLOW_BOX_CURSOR:
2410 NSRectFill (NSInsetRect (r, 1, 1));
2411 [FRAME_CURSOR_COLOR (f) set];
2418 /* If the character under cursor is R2L, draw the bar cursor
2419 on the right of its glyph, rather than on the left. */
2420 cursor_glyph = get_phys_cursor_glyph (w);
2421 if ((cursor_glyph->resolved_level & 1) != 0)
2422 s.origin.x += cursor_glyph->pixel_width - s.size.width;
2429 /* draw the character under the cursor */
2430 if (cursor_type != NO_CURSOR)
2431 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2433 #ifdef NS_IMPL_COCOA
2434 NSEnableScreenUpdates ();
2441 ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2442 /* --------------------------------------------------------------------------
2443 External (RIF): Draw a vertical line.
2444 -------------------------------------------------------------------------- */
2446 struct frame *f = XFRAME (WINDOW_FRAME (w));
2448 NSRect r = NSMakeRect (x, y0, 1, y1-y0);
2450 NSTRACE (ns_draw_vertical_window_border);
2452 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2454 [ns_lookup_indexed_color(face->foreground, f) set];
2456 ns_focus (f, &r, 1);
2463 show_hourglass (struct atimer *timer)
2465 if (hourglass_shown_p)
2470 /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */
2472 hourglass_shown_p = 1;
2478 hide_hourglass (void)
2480 if (!hourglass_shown_p)
2485 /* TODO: remove NSProgressIndicator from all frames */
2487 hourglass_shown_p = 0;
2493 /* ==========================================================================
2495 Glyph drawing operations
2497 ========================================================================== */
2500 ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2501 /* --------------------------------------------------------------------------
2502 Wrapper utility to account for internal border width on full-width lines,
2503 and allow top full-width rows to hit the frame top. nr should be pointer
2504 to two successive NSRects. Number of rects actually used is returned.
2505 -------------------------------------------------------------------------- */
2507 int n = get_glyph_string_clip_rects (s, nr, 2);
2511 /* --------------------------------------------------------------------
2512 Draw a wavy line under glyph string s. The wave fills wave_height
2519 wave_height = 3 | * * * *
2520 --------------------------------------------------------------------- */
2523 ns_draw_underwave (struct glyph_string *s, EmacsCGFloat width, EmacsCGFloat x)
2525 int wave_height = 3, wave_length = 2;
2526 int y, dx, dy, odd, xmax;
2531 dy = wave_height - 1;
2532 y = s->ybase - wave_height + 3;
2535 /* Find and set clipping rectangle */
2536 waveClip = NSMakeRect (x, y, width, wave_height);
2537 [[NSGraphicsContext currentContext] saveGraphicsState];
2538 NSRectClip (waveClip);
2540 /* Draw the waves */
2541 a.x = x - ((int)(x) % dx) + (EmacsCGFloat) 0.5;
2543 odd = (int)(a.x/dx) % 2;
2544 a.y = b.y = y + 0.5;
2553 [NSBezierPath strokeLineFromPoint:a toPoint:b];
2554 a.x = b.x, a.y = b.y;
2555 b.x += dx, b.y = y + 0.5 + odd*dy;
2559 /* Restore previous clipping rectangle(s) */
2560 [[NSGraphicsContext currentContext] restoreGraphicsState];
2566 ns_draw_text_decoration (struct glyph_string *s, struct face *face,
2567 NSColor *defaultCol, CGFloat width, CGFloat x)
2568 /* --------------------------------------------------------------------------
2569 Draw underline, overline, and strike-through on glyph string s.
2570 -------------------------------------------------------------------------- */
2572 if (s->for_overlaps)
2576 if (face->underline_p)
2578 if (s->face->underline_type == FACE_UNDER_WAVE)
2580 if (face->underline_defaulted_p)
2583 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2585 ns_draw_underwave (s, width, x);
2587 else if (s->face->underline_type == FACE_UNDER_LINE)
2591 unsigned long thickness, position;
2593 /* If the prev was underlined, match its appearance. */
2594 if (s->prev && s->prev->face->underline_p
2595 && s->prev->face->underline_type == FACE_UNDER_LINE
2596 && s->prev->underline_thickness > 0)
2598 thickness = s->prev->underline_thickness;
2599 position = s->prev->underline_position;
2604 unsigned long descent;
2607 descent = s->y + s->height - s->ybase;
2609 /* Use underline thickness of font, defaulting to 1. */
2610 thickness = (font && font->underline_thickness > 0)
2611 ? font->underline_thickness : 1;
2613 /* Determine the offset of underlining from the baseline. */
2614 if (x_underline_at_descent_line)
2615 position = descent - thickness;
2616 else if (x_use_underline_position_properties
2617 && font && font->underline_position >= 0)
2618 position = font->underline_position;
2620 position = lround (font->descent / 2);
2622 position = underline_minimum_offset;
2624 position = max (position, underline_minimum_offset);
2626 /* Ensure underlining is not cropped. */
2627 if (descent <= position)
2629 position = descent - 1;
2632 else if (descent < position + thickness)
2636 s->underline_thickness = thickness;
2637 s->underline_position = position;
2639 r = NSMakeRect (x, s->ybase + position, width, thickness);
2641 if (face->underline_defaulted_p)
2644 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2648 /* Do overline. We follow other terms in using a thickness of 1
2649 and ignoring overline_margin. */
2650 if (face->overline_p)
2653 r = NSMakeRect (x, s->y, width, 1);
2655 if (face->overline_color_defaulted_p)
2658 [ns_lookup_indexed_color (face->overline_color, s->f) set];
2662 /* Do strike-through. We follow other terms for thickness and
2663 vertical position.*/
2664 if (face->strike_through_p)
2669 dy = lrint ((s->height - 1) / 2);
2670 r = NSMakeRect (x, s->y + dy, width, 1);
2672 if (face->strike_through_color_defaulted_p)
2675 [ns_lookup_indexed_color (face->strike_through_color, s->f) set];
2681 ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
2682 char left_p, char right_p)
2683 /* --------------------------------------------------------------------------
2684 Draw an unfilled rect inside r, optionally leaving left and/or right open.
2685 Note we can't just use an NSDrawRect command, because of the possibility
2686 of some sides not being drawn, and because the rect will be filled.
2687 -------------------------------------------------------------------------- */
2693 s.size.height = thickness;
2695 s.origin.y += r.size.height - thickness;
2698 s.size.height = r.size.height;
2699 s.origin.y = r.origin.y;
2701 /* left, right (optional) */
2702 s.size.width = thickness;
2707 s.origin.x += r.size.width - thickness;
2714 ns_draw_relief (NSRect r, int thickness, char raised_p,
2715 char top_p, char bottom_p, char left_p, char right_p,
2716 struct glyph_string *s)
2717 /* --------------------------------------------------------------------------
2718 Draw a relief rect inside r, optionally leaving some sides open.
2719 Note we can't just use an NSDrawBezel command, because of the possibility
2720 of some sides not being drawn, and because the rect will be filled.
2721 -------------------------------------------------------------------------- */
2723 static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
2724 NSColor *newBaseCol = nil;
2727 NSTRACE (ns_draw_relief);
2731 if (s->face->use_box_color_for_shadows_p)
2733 newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f);
2735 /* else if (s->first_glyph->type == IMAGE_GLYPH
2737 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2739 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
2743 newBaseCol = ns_lookup_indexed_color (s->face->background, s->f);
2746 if (newBaseCol == nil)
2747 newBaseCol = [NSColor grayColor];
2749 if (newBaseCol != baseCol) /* TODO: better check */
2752 baseCol = [newBaseCol retain];
2754 lightCol = [[baseCol highlightWithLevel: 0.2] retain];
2756 darkCol = [[baseCol shadowWithLevel: 0.3] retain];
2759 [(raised_p ? lightCol : darkCol) set];
2761 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
2764 sr.size.height = thickness;
2765 if (top_p) NSRectFill (sr);
2768 sr.size.height = r.size.height;
2769 sr.size.width = thickness;
2770 if (left_p) NSRectFill (sr);
2772 [(raised_p ? darkCol : lightCol) set];
2775 sr.size.width = r.size.width;
2776 sr.size.height = thickness;
2777 sr.origin.y += r.size.height - thickness;
2778 if (bottom_p) NSRectFill (sr);
2781 sr.size.height = r.size.height;
2782 sr.origin.y = r.origin.y;
2783 sr.size.width = thickness;
2784 sr.origin.x += r.size.width - thickness;
2785 if (right_p) NSRectFill (sr);
2790 ns_dumpglyphs_box_or_relief (struct glyph_string *s)
2791 /* --------------------------------------------------------------------------
2792 Function modeled after x_draw_glyph_string_box ().
2793 Sets up parameters for drawing.
2794 -------------------------------------------------------------------------- */
2796 int right_x, last_x;
2797 char left_p, right_p;
2798 struct glyph *last_glyph;
2803 if (s->hl == DRAW_MOUSE_FACE)
2805 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2807 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2812 thickness = face->box_line_width;
2814 NSTRACE (ns_dumpglyphs_box_or_relief);
2816 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2817 ? WINDOW_RIGHT_EDGE_X (s->w)
2818 : window_box_right (s->w, s->area));
2819 last_glyph = (s->cmp || s->img
2820 ? s->first_glyph : s->first_glyph + s->nchars-1);
2822 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2823 ? last_x - 1 : min (last_x, s->x + s->background_width) - 1));
2825 left_p = (s->first_glyph->left_box_line_p
2826 || (s->hl == DRAW_MOUSE_FACE
2827 && (s->prev == NULL || s->prev->hl != s->hl)));
2828 right_p = (last_glyph->right_box_line_p
2829 || (s->hl == DRAW_MOUSE_FACE
2830 && (s->next == NULL || s->next->hl != s->hl)));
2832 r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
2834 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
2835 if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
2837 ns_draw_box (r, abs (thickness),
2838 ns_lookup_indexed_color (face->box_color, s->f),
2843 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
2844 1, 1, left_p, right_p, s);
2850 ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
2851 /* --------------------------------------------------------------------------
2852 Modeled after x_draw_glyph_string_background, which draws BG in
2853 certain cases. Others are left to the text rendering routine.
2854 -------------------------------------------------------------------------- */
2856 NSTRACE (ns_maybe_dumpglyphs_background);
2858 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
2860 int box_line_width = max (s->face->box_line_width, 0);
2861 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2862 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
2865 if (s->hl == DRAW_MOUSE_FACE)
2867 face = FACE_FROM_ID (s->f,
2868 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2870 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2873 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2875 [(NS_FACE_BACKGROUND (face) != 0
2876 ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
2877 : FRAME_BACKGROUND_COLOR (s->f)) set];
2880 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
2881 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
2884 if (s->hl != DRAW_CURSOR)
2886 NSRect r = NSMakeRect (s->x, s->y + box_line_width,
2887 s->background_width,
2888 s->height-2*box_line_width);
2892 s->background_filled_p = 1;
2899 ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
2900 /* --------------------------------------------------------------------------
2901 Renders an image and associated borders.
2902 -------------------------------------------------------------------------- */
2904 EmacsImage *img = s->img->pixmap;
2905 int box_line_vwidth = max (s->face->box_line_width, 0);
2906 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2907 int bg_x, bg_y, bg_height;
2914 NSTRACE (ns_dumpglyphs_image);
2916 if (s->face->box != FACE_NO_BOX
2917 && s->first_glyph->left_box_line_p && s->slice.x == 0)
2918 x += abs (s->face->box_line_width);
2921 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
2922 bg_height = s->height;
2923 /* other terms have this, but was causing problems w/tabbar mode */
2924 /* - 2 * box_line_vwidth; */
2926 if (s->slice.x == 0) x += s->img->hmargin;
2927 if (s->slice.y == 0) y += s->img->vmargin;
2929 /* Draw BG: if we need larger area than image itself cleared, do that,
2930 otherwise, since we composite the image under NS (instead of mucking
2931 with its background color), we must clear just the image area. */
2932 if (s->hl == DRAW_MOUSE_FACE)
2934 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2936 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2939 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2941 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set];
2943 if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin
2944 || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width)
2946 br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height);
2947 s->background_filled_p = 1;
2951 br = NSMakeRect (x, y, s->slice.width, s->slice.height);
2956 /* Draw the image.. do we need to draw placeholder if img ==nil? */
2959 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
2960 NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height);
2961 NSRect ir = NSMakeRect (s->slice.x, s->slice.y,
2962 s->slice.width, s->slice.height);
2965 operation: NSCompositeSourceOver
2970 [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
2971 operation: NSCompositeSourceOver];
2975 if (s->hl == DRAW_CURSOR)
2977 [FRAME_CURSOR_COLOR (s->f) set];
2978 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
2979 tdCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
2981 /* Currently on NS img->mask is always 0. Since
2982 get_window_cursor_type specifies a hollow box cursor when on
2983 a non-masked image we never reach this clause. But we put it
2984 in in anticipation of better support for image masks on
2986 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
2990 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
2993 /* Draw underline, overline, strike-through. */
2994 ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x);
2996 /* Draw relief, if requested */
2997 if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
2999 if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
3001 th = tool_bar_button_relief >= 0 ?
3002 tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3003 raised_p = (s->hl == DRAW_IMAGE_RAISED);
3007 th = abs (s->img->relief);
3008 raised_p = (s->img->relief > 0);
3011 r.origin.x = x - th;
3012 r.origin.y = y - th;
3013 r.size.width = s->slice.width + 2*th-1;
3014 r.size.height = s->slice.height + 2*th-1;
3015 ns_draw_relief (r, th, raised_p,
3017 s->slice.y + s->slice.height == s->img->height,
3019 s->slice.x + s->slice.width == s->img->width, s);
3022 /* If there is no mask, the background won't be seen,
3023 so draw a rectangle on the image for the cursor.
3024 Do this for all images, getting transparency right is not reliable. */
3025 if (s->hl == DRAW_CURSOR)
3027 int thickness = abs (s->img->relief);
3028 if (thickness == 0) thickness = 1;
3029 ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
3035 ns_dumpglyphs_stretch (struct glyph_string *s)
3040 NSColor *fgCol, *bgCol;
3042 if (!s->background_filled_p)
3044 n = ns_get_glyph_string_clip_rect (s, r);
3045 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
3047 ns_focus (s->f, r, n);
3049 if (s->hl == DRAW_MOUSE_FACE)
3051 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3053 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3056 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3058 bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3059 fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3061 for (i = 0; i < n; ++i)
3063 if (!s->row->full_width_p)
3065 int overrun, leftoverrun;
3067 /* truncate to avoid overwriting fringe and/or scrollbar */
3068 overrun = max (0, (s->x + s->background_width)
3069 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
3070 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
3071 r[i].size.width -= overrun;
3073 /* truncate to avoid overwriting to left of the window box */
3074 leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
3075 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
3077 if (leftoverrun > 0)
3079 r[i].origin.x += leftoverrun;
3080 r[i].size.width -= leftoverrun;
3083 /* XXX: Try to work between problem where a stretch glyph on
3084 a partially-visible bottom row will clear part of the
3085 modeline, and another where list-buffers headers and similar
3086 rows erroneously have visible_height set to 0. Not sure
3087 where this is coming from as other terms seem not to show. */
3088 r[i].size.height = min (s->height, s->row->visible_height);
3093 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
3094 overwriting cursor (usually when cursor on a tab) */
3095 if (s->hl == DRAW_CURSOR)
3100 width = s->w->phys_cursor_width;
3101 r[i].size.width -= width;
3102 r[i].origin.x += width;
3106 /* Draw overlining, etc. on the cursor. */
3107 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3108 ns_draw_text_decoration (s, face, bgCol, width, x);
3110 ns_draw_text_decoration (s, face, fgCol, width, x);
3117 /* Draw overlining, etc. on the stretch glyph (or the part
3118 of the stretch glyph after the cursor). */
3119 ns_draw_text_decoration (s, face, fgCol, r[i].size.width,
3123 s->background_filled_p = 1;
3129 ns_draw_glyph_string (struct glyph_string *s)
3130 /* --------------------------------------------------------------------------
3131 External (RIF): Main draw-text call.
3132 -------------------------------------------------------------------------- */
3134 /* TODO (optimize): focus for box and contents draw */
3137 char box_drawn_p = 0;
3139 NSTRACE (ns_draw_glyph_string);
3141 if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
3144 struct glyph_string *next;
3146 for (width = 0, next = s->next;
3147 next && width < s->right_overhang;
3148 width += next->width, next = next->next)
3149 if (next->first_glyph->type != IMAGE_GLYPH)
3151 if (next->first_glyph->type != STRETCH_GLYPH)
3153 n = ns_get_glyph_string_clip_rect (s->next, r);
3154 ns_focus (s->f, r, n);
3155 ns_maybe_dumpglyphs_background (s->next, 1);
3160 ns_dumpglyphs_stretch (s->next);
3162 next->num_clips = 0;
3166 if (!s->for_overlaps && s->face->box != FACE_NO_BOX
3167 && (s->first_glyph->type == CHAR_GLYPH
3168 || s->first_glyph->type == COMPOSITE_GLYPH))
3170 n = ns_get_glyph_string_clip_rect (s, r);
3171 ns_focus (s->f, r, n);
3172 ns_maybe_dumpglyphs_background (s, 1);
3173 ns_dumpglyphs_box_or_relief (s);
3178 switch (s->first_glyph->type)
3182 n = ns_get_glyph_string_clip_rect (s, r);
3183 ns_focus (s->f, r, n);
3184 ns_dumpglyphs_image (s, r[0]);
3189 ns_dumpglyphs_stretch (s);
3193 case COMPOSITE_GLYPH:
3194 n = ns_get_glyph_string_clip_rect (s, r);
3195 ns_focus (s->f, r, n);
3197 if (s->for_overlaps || (s->cmp_from > 0
3198 && ! s->first_glyph->u.cmp.automatic))
3199 s->background_filled_p = 1;
3201 ns_maybe_dumpglyphs_background
3202 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3204 ns_tmp_flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
3205 (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
3206 (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
3207 NS_DUMPGLYPH_NORMAL));
3208 ns_tmp_font = (struct nsfont_info *)s->face->font;
3209 if (ns_tmp_font == NULL)
3210 ns_tmp_font = (struct nsfont_info *)FRAME_FONT (s->f);
3212 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3214 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3215 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3216 NS_FACE_FOREGROUND (s->face) = tmp;
3219 ns_tmp_font->font.driver->draw
3220 (s, 0, s->nchars, s->x, s->y,
3221 (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
3222 || ns_tmp_flags == NS_DUMPGLYPH_MOUSEFACE);
3224 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3226 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3227 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3228 NS_FACE_FOREGROUND (s->face) = tmp;
3234 case GLYPHLESS_GLYPH:
3235 n = ns_get_glyph_string_clip_rect (s, r);
3236 ns_focus (s->f, r, n);
3238 if (s->for_overlaps || (s->cmp_from > 0
3239 && ! s->first_glyph->u.cmp.automatic))
3240 s->background_filled_p = 1;
3242 ns_maybe_dumpglyphs_background
3243 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3245 /* Not yet implemented. */
3254 /* Draw box if not done already. */
3255 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
3257 n = ns_get_glyph_string_clip_rect (s, r);
3258 ns_focus (s->f, r, n);
3259 ns_dumpglyphs_box_or_relief (s);
3268 /* ==========================================================================
3272 ========================================================================== */
3276 ns_send_appdefined (int value)
3277 /* --------------------------------------------------------------------------
3278 Internal: post an appdefined event which EmacsApp-sendEvent will
3279 recognize and take as a command to halt the event loop.
3280 -------------------------------------------------------------------------- */
3282 /*NSTRACE (ns_send_appdefined); */
3284 #ifdef NS_IMPL_GNUSTEP
3285 // GNUStep needs postEvent to happen on the main thread.
3286 if (! [[NSThread currentThread] isMainThread])
3288 EmacsApp *app = (EmacsApp *)NSApp;
3289 app->nextappdefined = value;
3290 [app performSelectorOnMainThread:@selector (sendFromMainThread:)
3297 /* Only post this event if we haven't already posted one. This will end
3298 the [NXApp run] main loop after having processed all events queued at
3300 if (send_appdefined)
3304 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
3305 send_appdefined = NO;
3307 /* Don't need wakeup timer any more */
3310 [timed_entry invalidate];
3311 [timed_entry release];
3315 nxev = [NSEvent otherEventWithType: NSApplicationDefined
3316 location: NSMakePoint (0, 0)
3319 windowNumber: [[NSApp mainWindow] windowNumber]
3320 context: [NSApp context]
3325 /* Post an application defined event on the event queue. When this is
3326 received the [NXApp run] will return, thus having processed all
3327 events which are currently queued. */
3328 [NSApp postEvent: nxev atStart: NO];
3332 #ifdef HAVE_NATIVE_FS
3336 Lisp_Object frame, tail;
3338 if (ns_last_use_native_fullscreen == ns_use_native_fullscreen)
3341 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
3343 /* Clear the mouse-moved flag for every frame on this display. */
3344 FOR_EACH_FRAME (tail, frame)
3346 struct frame *f = XFRAME (frame);
3349 EmacsView *view = FRAME_NS_VIEW (f);
3350 [view updateCollectionBehaviour];
3356 /* GNUStep and OSX <= 10.4 does not have cancelTracking. */
3357 #if defined (NS_IMPL_COCOA) && \
3358 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
3359 /* Check if menu open should be cancelled or continued as normal. */
3361 ns_check_menu_open (NSMenu *menu)
3363 /* Click in menu bar? */
3364 NSArray *a = [[NSApp mainMenu] itemArray];
3368 if (menu == nil) // Menu tracking ended.
3370 if (menu_will_open_state == MENU_OPENING)
3371 menu_will_open_state = MENU_NONE;
3375 for (i = 0; ! found && i < [a count]; i++)
3376 found = menu == [[a objectAtIndex:i] submenu];
3379 if (menu_will_open_state == MENU_NONE && emacs_event)
3381 NSEvent *theEvent = [NSApp currentEvent];
3382 struct frame *emacsframe = SELECTED_FRAME ();
3384 [menu cancelTracking];
3385 menu_will_open_state = MENU_PENDING;
3386 emacs_event->kind = MENU_BAR_ACTIVATE_EVENT;
3387 EV_TRAILER (theEvent);
3389 CGEventRef ourEvent = CGEventCreate (NULL);
3390 menu_mouse_point = CGEventGetLocation (ourEvent);
3391 CFRelease (ourEvent);
3393 else if (menu_will_open_state == MENU_OPENING)
3395 menu_will_open_state = MENU_NONE;
3400 /* Redo saved menu click if state is MENU_PENDING. */
3402 ns_check_pending_open_menu ()
3404 if (menu_will_open_state == MENU_PENDING)
3406 CGEventSourceRef source
3407 = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
3409 CGEventRef event = CGEventCreateMouseEvent (source,
3410 kCGEventLeftMouseDown,
3412 kCGMouseButtonLeft);
3413 CGEventSetType (event, kCGEventLeftMouseDown);
3414 CGEventPost (kCGHIDEventTap, event);
3418 menu_will_open_state = MENU_OPENING;
3421 #endif /* NS_IMPL_COCOA) && >= MAC_OS_X_VERSION_10_5 */
3424 ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3425 /* --------------------------------------------------------------------------
3426 External (hook): Post an event to ourself and keep reading events until
3427 we read it back again. In effect process all events which were waiting.
3428 From 21+ we have to manage the event buffer ourselves.
3429 -------------------------------------------------------------------------- */
3431 struct input_event ev;
3434 /* NSTRACE (ns_read_socket); */
3436 #ifdef HAVE_NATIVE_FS
3440 if ([NSApp modalWindow] != nil)
3443 if (hold_event_q.nr > 0)
3446 for (i = 0; i < hold_event_q.nr; ++i)
3447 kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit);
3448 hold_event_q.nr = 0;
3453 n_emacs_events_pending = 0;
3456 q_event_ptr = hold_quit;
3458 /* we manage autorelease pools by allocate/reallocate each time around
3459 the loop; strict nesting is occasionally violated but seems not to
3460 matter.. earlier methods using full nesting caused major memory leaks */
3461 [outerpool release];
3462 outerpool = [[NSAutoreleasePool alloc] init];
3464 /* If have pending open-file requests, attend to the next one of those. */
3465 if (ns_pending_files && [ns_pending_files count] != 0
3466 && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]])
3468 [ns_pending_files removeObjectAtIndex: 0];
3470 /* Deal with pending service requests. */
3471 else if (ns_pending_service_names && [ns_pending_service_names count] != 0
3473 NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
3474 withArg: [ns_pending_service_args objectAtIndex: 0]])
3476 [ns_pending_service_names removeObjectAtIndex: 0];
3477 [ns_pending_service_args removeObjectAtIndex: 0];
3481 /* Run and wait for events. We must always send one NX_APPDEFINED event
3482 to ourself, otherwise [NXApp run] will never exit. */
3483 send_appdefined = YES;
3484 ns_send_appdefined (-1);
3486 if (++apploopnr != 1)
3494 nevents = n_emacs_events_pending;
3495 n_emacs_events_pending = 0;
3496 emacs_event = q_event_ptr = NULL;
3504 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3505 fd_set *exceptfds, struct timespec const *timeout,
3506 sigset_t const *sigmask)
3507 /* --------------------------------------------------------------------------
3508 Replacement for select, checking for events
3509 -------------------------------------------------------------------------- */
3513 struct input_event event;
3516 /* NSTRACE (ns_select); */
3518 #ifdef HAVE_NATIVE_FS
3522 if (hold_event_q.nr > 0)
3524 /* We already have events pending. */
3530 for (k = 0; k < nfds+1; k++)
3532 if (readfds && FD_ISSET(k, readfds)) ++nr;
3533 if (writefds && FD_ISSET(k, writefds)) ++nr;
3537 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
3538 return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
3540 [outerpool release];
3541 outerpool = [[NSAutoreleasePool alloc] init];
3544 send_appdefined = YES;
3547 pthread_mutex_lock (&select_mutex);
3552 select_readfds = *readfds;
3553 select_valid += SELECT_HAVE_READ;
3557 select_writefds = *writefds;
3558 select_valid += SELECT_HAVE_WRITE;
3563 select_timeout = *timeout;
3564 select_valid += SELECT_HAVE_TMO;
3567 pthread_mutex_unlock (&select_mutex);
3569 /* Inform fd_handler that select should be called */
3571 emacs_write_sig (selfds[1], &c, 1);
3573 else if (nr == 0 && timeout)
3575 /* No file descriptor, just a timeout, no need to wake fd_handler */
3576 double time = timespectod (*timeout);
3577 timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
3580 @selector (timeout_handler:)
3585 else /* No timeout and no file descriptors, can this happen? */
3587 /* Send appdefined so we exit from the loop */
3588 ns_send_appdefined (-1);
3593 emacs_event = &event;
3594 if (++apploopnr != 1)
3601 if (nr > 0 && readfds)
3604 emacs_write_sig (selfds[1], &c, 1);
3608 t = last_appdefined_event_data;
3610 if (t != NO_APPDEFINED_DATA)
3612 last_appdefined_event_data = NO_APPDEFINED_DATA;
3616 /* The NX_APPDEFINED event we received was a timeout. */
3621 /* The NX_APPDEFINED event we received was the result of
3622 at least one real input event arriving. */
3628 /* Received back from select () in fd_handler; copy the results */
3629 pthread_mutex_lock (&select_mutex);
3630 if (readfds) *readfds = select_readfds;
3631 if (writefds) *writefds = select_writefds;
3632 pthread_mutex_unlock (&select_mutex);
3647 /* ==========================================================================
3651 ========================================================================== */
3655 ns_set_vertical_scroll_bar (struct window *window,
3656 int portion, int whole, int position)
3657 /* --------------------------------------------------------------------------
3658 External (hook): Update or add scrollbar
3659 -------------------------------------------------------------------------- */
3663 struct frame *f = XFRAME (WINDOW_FRAME (window));
3664 EmacsView *view = FRAME_NS_VIEW (f);
3665 int window_y, window_height;
3666 int top, left, height, width, sb_width, sb_left;
3668 BOOL fringe_extended_p;
3670 /* optimization; display engine sends WAY too many of these.. */
3671 if (!NILP (window->vertical_scroll_bar))
3673 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3674 if ([bar checkSamePosition: position portion: portion whole: whole])
3676 if (view->scrollbarsNeedingUpdate == 0)
3678 if (!windows_or_buffers_changed)
3682 view->scrollbarsNeedingUpdate--;
3686 NSTRACE (ns_set_vertical_scroll_bar);
3688 /* Get dimensions. */
3689 window_box (window, ANY_AREA, 0, &window_y, 0, &window_height);
3691 height = window_height;
3692 width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
3693 left = WINDOW_SCROLL_BAR_AREA_X (window);
3695 /* allow for displaying a skinnier scrollbar than char area allotted */
3696 sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ?
3697 WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width;
3700 r = NSMakeRect (sb_left, top, sb_width, height);
3701 /* the parent view is flipped, so we need to flip y value */
3703 r.origin.y = (v.size.height - r.size.height - r.origin.y);
3705 fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (window);
3707 XSETWINDOW (win, window);
3710 /* we want at least 5 lines to display a scrollbar */
3711 if (WINDOW_TOTAL_LINES (window) < 5)
3713 if (!NILP (window->vertical_scroll_bar))
3715 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3716 [bar removeFromSuperview];
3717 wset_vertical_scroll_bar (window, Qnil);
3719 ns_clear_frame_area (f, sb_left, top, width, height);
3724 if (NILP (window->vertical_scroll_bar))
3726 if (width > 0 && height > 0)
3728 if (fringe_extended_p)
3729 ns_clear_frame_area (f, sb_left, top, sb_width, height);
3731 ns_clear_frame_area (f, left, top, width, height);
3734 bar = [[EmacsScroller alloc] initFrame: r window: win];
3735 wset_vertical_scroll_bar (window, make_save_ptr (bar));
3740 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3741 oldRect = [bar frame];
3742 r.size.width = oldRect.size.width;
3743 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
3745 if (oldRect.origin.x != r.origin.x)
3746 ns_clear_frame_area (f, sb_left, top, width, height);
3751 [bar setPosition: position portion: portion whole: whole];
3757 ns_condemn_scroll_bars (struct frame *f)
3758 /* --------------------------------------------------------------------------
3759 External (hook): arrange for all frame's scrollbars to be removed
3760 at next call to judge_scroll_bars, except for those redeemed.
3761 -------------------------------------------------------------------------- */
3765 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
3767 NSTRACE (ns_condemn_scroll_bars);
3769 for (i =[subviews count]-1; i >= 0; i--)
3771 view = [subviews objectAtIndex: i];
3772 if ([view isKindOfClass: [EmacsScroller class]])
3779 ns_redeem_scroll_bar (struct window *window)
3780 /* --------------------------------------------------------------------------
3781 External (hook): arrange to spare this window's scrollbar
3782 at next call to judge_scroll_bars.
3783 -------------------------------------------------------------------------- */
3786 NSTRACE (ns_redeem_scroll_bar);
3787 if (!NILP (window->vertical_scroll_bar))
3789 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3796 ns_judge_scroll_bars (struct frame *f)
3797 /* --------------------------------------------------------------------------
3798 External (hook): destroy all scrollbars on frame that weren't
3799 redeemed after call to condemn_scroll_bars.
3800 -------------------------------------------------------------------------- */
3804 EmacsView *eview = FRAME_NS_VIEW (f);
3805 NSArray *subviews = [[eview superview] subviews];
3808 NSTRACE (ns_judge_scroll_bars);
3809 for (i = [subviews count]-1; i >= 0; --i)
3811 view = [subviews objectAtIndex: i];
3812 if (![view isKindOfClass: [EmacsScroller class]]) continue;
3818 [eview updateFrameSize: NO];
3821 /* ==========================================================================
3825 ========================================================================== */
3828 x_display_pixel_height (struct ns_display_info *dpyinfo)
3830 NSArray *screens = [NSScreen screens];
3831 NSEnumerator *enumerator = [screens objectEnumerator];
3836 while ((screen = [enumerator nextObject]) != nil)
3837 frame = NSUnionRect (frame, [screen frame]);
3839 return NSHeight (frame);
3843 x_display_pixel_width (struct ns_display_info *dpyinfo)
3845 NSArray *screens = [NSScreen screens];
3846 NSEnumerator *enumerator = [screens objectEnumerator];
3851 while ((screen = [enumerator nextObject]) != nil)
3852 frame = NSUnionRect (frame, [screen frame]);
3854 return NSWidth (frame);
3858 static Lisp_Object ns_string_to_lispmod (const char *s)
3859 /* --------------------------------------------------------------------------
3860 Convert modifier name to lisp symbol
3861 -------------------------------------------------------------------------- */
3863 if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10))
3865 else if (!strncmp (SSDATA (SYMBOL_NAME (Qsuper)), s, 10))
3867 else if (!strncmp (SSDATA (SYMBOL_NAME (Qcontrol)), s, 10))
3869 else if (!strncmp (SSDATA (SYMBOL_NAME (Qalt)), s, 10))
3871 else if (!strncmp (SSDATA (SYMBOL_NAME (Qhyper)), s, 10))
3873 else if (!strncmp (SSDATA (SYMBOL_NAME (Qnone)), s, 10))
3881 ns_default (const char *parameter, Lisp_Object *result,
3882 Lisp_Object yesval, Lisp_Object noval,
3883 BOOL is_float, BOOL is_modstring)
3884 /* --------------------------------------------------------------------------
3885 Check a parameter value in user's preferences
3886 -------------------------------------------------------------------------- */
3888 const char *value = ns_get_defaults_value (parameter);
3894 if (c_strcasecmp (value, "YES") == 0)
3896 else if (c_strcasecmp (value, "NO") == 0)
3898 else if (is_float && (f = strtod (value, &pos), pos != value))
3899 *result = make_float (f);
3900 else if (is_modstring && value)
3901 *result = ns_string_to_lispmod (value);
3902 else fprintf (stderr,
3903 "Bad value for default \"%s\": \"%s\"\n", parameter, value);
3909 ns_initialize_display_info (struct ns_display_info *dpyinfo)
3910 /* --------------------------------------------------------------------------
3911 Initialize global info and storage for display.
3912 -------------------------------------------------------------------------- */
3914 NSScreen *screen = [NSScreen mainScreen];
3915 NSWindowDepth depth = [screen depth];
3917 dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
3918 dpyinfo->resy = 72.27;
3919 dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
3920 NSColorSpaceFromDepth (depth)]
3921 && ![NSCalibratedWhiteColorSpace isEqualToString:
3922 NSColorSpaceFromDepth (depth)];
3923 dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
3924 dpyinfo->image_cache = make_image_cache ();
3925 dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table);
3926 dpyinfo->color_table->colors = NULL;
3927 dpyinfo->root_window = 42; /* a placeholder.. */
3928 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL;
3929 dpyinfo->n_fonts = 0;
3930 dpyinfo->smallest_font_height = 1;
3931 dpyinfo->smallest_char_width = 1;
3933 reset_mouse_highlight (&dpyinfo->mouse_highlight);
3937 /* This and next define (many of the) public functions in this file. */
3938 /* x_... are generic versions in xdisp.c that we, and other terms, get away
3939 with using despite presence in the "system dependent" redisplay
3940 interface. In addition, many of the ns_ methods have code that is
3941 shared with all terms, indicating need for further refactoring. */
3942 extern frame_parm_handler ns_frame_parm_handlers[];
3943 static struct redisplay_interface ns_redisplay_interface =
3945 ns_frame_parm_handlers,
3949 x_clear_end_of_line,
3951 ns_after_update_window_line,
3952 ns_update_window_begin,
3953 ns_update_window_end,
3954 0, /* flush_display */
3955 x_clear_window_mouse_face,
3956 x_get_glyph_overhangs,
3957 x_fix_overlapping_area,
3958 ns_draw_fringe_bitmap,
3959 0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
3960 0, /* destroy_fringe_bitmap */
3961 ns_compute_glyph_string_overhangs,
3962 ns_draw_glyph_string, /* interface to nsfont.m */
3963 ns_define_frame_cursor,
3964 ns_clear_frame_area,
3965 ns_draw_window_cursor,
3966 ns_draw_vertical_window_border,
3967 ns_shift_glyphs_for_insert
3972 ns_delete_display (struct ns_display_info *dpyinfo)
3978 /* This function is called when the last frame on a display is deleted. */
3980 ns_delete_terminal (struct terminal *terminal)
3982 struct ns_display_info *dpyinfo = terminal->display_info.ns;
3984 /* Protect against recursive calls. delete_frame in
3985 delete_terminal calls us back when it deletes our last frame. */
3986 if (!terminal->name)
3991 x_destroy_all_bitmaps (dpyinfo);
3992 ns_delete_display (dpyinfo);
3997 static struct terminal *
3998 ns_create_terminal (struct ns_display_info *dpyinfo)
3999 /* --------------------------------------------------------------------------
4000 Set up use of NS before we make the first connection.
4001 -------------------------------------------------------------------------- */
4003 struct terminal *terminal;
4005 NSTRACE (ns_create_terminal);
4007 terminal = create_terminal ();
4009 terminal->type = output_ns;
4010 terminal->display_info.ns = dpyinfo;
4011 dpyinfo->terminal = terminal;
4013 terminal->rif = &ns_redisplay_interface;
4015 terminal->clear_frame_hook = ns_clear_frame;
4016 terminal->ins_del_lines_hook = 0; /* XXX vestigial? */
4017 terminal->delete_glyphs_hook = 0; /* XXX vestigial? */
4018 terminal->ring_bell_hook = ns_ring_bell;
4019 terminal->reset_terminal_modes_hook = NULL;
4020 terminal->set_terminal_modes_hook = NULL;
4021 terminal->update_begin_hook = ns_update_begin;
4022 terminal->update_end_hook = ns_update_end;
4023 terminal->set_terminal_window_hook = NULL; /* XXX vestigial? */
4024 terminal->read_socket_hook = ns_read_socket;
4025 terminal->frame_up_to_date_hook = ns_frame_up_to_date;
4026 terminal->mouse_position_hook = ns_mouse_position;
4027 terminal->frame_rehighlight_hook = ns_frame_rehighlight;
4028 terminal->frame_raise_lower_hook = ns_frame_raise_lower;
4030 terminal->fullscreen_hook = ns_fullscreen_hook;
4032 terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
4033 terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
4034 terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
4035 terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
4037 terminal->delete_frame_hook = x_destroy_window;
4038 terminal->delete_terminal_hook = ns_delete_terminal;
4040 terminal->scroll_region_ok = 1;
4041 terminal->char_ins_del_ok = 1;
4042 terminal->line_ins_del_ok = 1;
4043 terminal->fast_clear_end_of_line = 1;
4044 terminal->memory_below_frame = 0;
4050 struct ns_display_info *
4051 ns_term_init (Lisp_Object display_name)
4052 /* --------------------------------------------------------------------------
4053 Start the Application and get things rolling.
4054 -------------------------------------------------------------------------- */
4056 struct terminal *terminal;
4057 struct ns_display_info *dpyinfo;
4058 static int ns_initialized = 0;
4061 if (ns_initialized) return x_display_list;
4064 NSTRACE (ns_term_init);
4066 [outerpool release];
4067 outerpool = [[NSAutoreleasePool alloc] init];
4069 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
4070 /*GSDebugAllocationActive (YES); */
4074 Fset_input_interrupt_mode (Qnil);
4076 if (selfds[0] == -1)
4078 if (emacs_pipe (selfds) != 0)
4080 fprintf (stderr, "Failed to create pipe: %s\n",
4081 emacs_strerror (errno));
4085 fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
4086 FD_ZERO (&select_readfds);
4087 FD_ZERO (&select_writefds);
4088 pthread_mutex_init (&select_mutex, NULL);
4091 ns_pending_files = [[NSMutableArray alloc] init];
4092 ns_pending_service_names = [[NSMutableArray alloc] init];
4093 ns_pending_service_args = [[NSMutableArray alloc] init];
4095 /* Start app and create the main menu, window, view.
4096 Needs to be here because ns_initialize_display_info () uses AppKit classes.
4097 The view will then ask the NSApp to stop and return to Emacs. */
4098 [EmacsApp sharedApplication];
4101 [NSApp setDelegate: NSApp];
4103 /* Start the select thread. */
4104 [NSThread detachNewThreadSelector:@selector (fd_handler:)
4108 /* debugging: log all notifications */
4109 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
4110 selector: @selector (logNotification:)
4111 name: nil object: nil]; */
4113 dpyinfo = xzalloc (sizeof *dpyinfo);
4115 ns_initialize_display_info (dpyinfo);
4116 terminal = ns_create_terminal (dpyinfo);
4118 terminal->kboard = xmalloc (sizeof *terminal->kboard);
4119 init_kboard (terminal->kboard);
4120 kset_window_system (terminal->kboard, Qns);
4121 terminal->kboard->next_kboard = all_kboards;
4122 all_kboards = terminal->kboard;
4123 /* Don't let the initial kboard remain current longer than necessary.
4124 That would cause problems if a file loaded on startup tries to
4125 prompt in the mini-buffer. */
4126 if (current_kboard == initial_kboard)
4127 current_kboard = terminal->kboard;
4128 terminal->kboard->reference_count++;
4130 dpyinfo->next = x_display_list;
4131 x_display_list = dpyinfo;
4133 /* Put it on ns_display_name_list */
4134 ns_display_name_list = Fcons (Fcons (display_name, Qnil),
4135 ns_display_name_list);
4136 dpyinfo->name_list_element = XCAR (ns_display_name_list);
4138 terminal->name = xstrdup (SSDATA (display_name));
4142 if (!inhibit_x_resources)
4144 ns_default ("GSFontAntiAlias", &ns_antialias_text,
4147 /* this is a standard variable */
4148 ns_default ("AppleAntiAliasingThreshold", &tmp,
4149 make_float (10.0), make_float (6.0), YES, NO);
4150 ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
4153 ns_selection_color = [[NSUserDefaults standardUserDefaults]
4154 stringForKey: @"AppleHighlightColor"];
4155 if (ns_selection_color == nil)
4156 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
4159 NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
4163 Lisp_Object color_file, color_map, color;
4167 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4168 Fsymbol_value (intern ("data-directory")));
4170 color_map = Fx_load_color_file (color_file);
4171 if (NILP (color_map))
4172 fatal ("Could not read %s.\n", SDATA (color_file));
4174 cl = [[NSColorList alloc] initWithName: @"Emacs"];
4175 for ( ; CONSP (color_map); color_map = XCDR (color_map))
4177 color = XCAR (color_map);
4178 name = SSDATA (XCAR (color));
4179 c = XINT (XCDR (color));
4181 [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0
4182 green: GREEN_FROM_ULONG (c) / 255.0
4183 blue: BLUE_FROM_ULONG (c) / 255.0
4185 forKey: [NSString stringWithUTF8String: name]];
4187 [cl writeToFile: nil];
4192 #ifdef NS_IMPL_GNUSTEP
4193 Vwindow_system_version = build_string (gnustep_base_version);
4195 /*PSnextrelease (128, c); */
4196 char c[DBL_BUFSIZE_BOUND];
4197 int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber);
4198 Vwindow_system_version = make_unibyte_string (c, len);
4202 delete_keyboard_wait_descriptor (0);
4204 ns_app_name = [[NSProcessInfo processInfo] processName];
4206 /* Set up OS X app menu */
4207 #ifdef NS_IMPL_COCOA
4211 /* set up the application menu */
4212 svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
4213 [svcsMenu setAutoenablesItems: NO];
4214 appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
4215 [appMenu setAutoenablesItems: NO];
4216 mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
4217 dockMenu = [[EmacsMenu alloc] initWithTitle: @""];
4219 [appMenu insertItemWithTitle: @"About Emacs"
4220 action: @selector (orderFrontStandardAboutPanel:)
4223 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
4224 [appMenu insertItemWithTitle: @"Preferences..."
4225 action: @selector (showPreferencesWindow:)
4228 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
4229 item = [appMenu insertItemWithTitle: @"Services"
4230 action: @selector (menuDown:)
4233 [appMenu setSubmenu: svcsMenu forItem: item];
4234 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];
4235 [appMenu insertItemWithTitle: @"Hide Emacs"
4236 action: @selector (hide:)
4239 item = [appMenu insertItemWithTitle: @"Hide Others"
4240 action: @selector (hideOtherApplications:)
4243 [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
4244 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8];
4245 [appMenu insertItemWithTitle: @"Quit Emacs"
4246 action: @selector (terminate:)
4250 item = [mainMenu insertItemWithTitle: ns_app_name
4251 action: @selector (menuDown:)
4254 [mainMenu setSubmenu: appMenu forItem: item];
4255 [dockMenu insertItemWithTitle: @"New Frame"
4256 action: @selector (newFrame:)
4260 [NSApp setMainMenu: mainMenu];
4261 [NSApp setAppleMenu: appMenu];
4262 [NSApp setServicesMenu: svcsMenu];
4263 /* Needed at least on Cocoa, to get dock menu to show windows */
4264 [NSApp setWindowsMenu: [[NSMenu alloc] init]];
4266 [[NSNotificationCenter defaultCenter]
4267 addObserver: mainMenu
4268 selector: @selector (trackingNotification:)
4269 name: NSMenuDidBeginTrackingNotification object: mainMenu];
4270 [[NSNotificationCenter defaultCenter]
4271 addObserver: mainMenu
4272 selector: @selector (trackingNotification:)
4273 name: NSMenuDidEndTrackingNotification object: mainMenu];
4275 #endif /* MAC OS X menu setup */
4277 /* Register our external input/output types, used for determining
4278 applicable services and also drag/drop eligibility. */
4279 ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
4280 ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
4282 ns_drag_types = [[NSArray arrayWithObjects:
4284 NSTabularTextPboardType,
4285 NSFilenamesPboardType,
4288 NSFontPboardType, nil] retain];
4290 /* If fullscreen is in init/default-frame-alist, focus isn't set
4291 right for fullscreen windows, so set this. */
4292 [NSApp activateIgnoringOtherApps:YES];
4295 ns_do_open_file = YES;
4297 #ifdef NS_IMPL_GNUSTEP
4298 /* GNUstep steals SIGCHLD for use in NSTask, but we don't use NSTask.
4299 We must re-catch it so subprocess works. */
4300 catch_child_signal ();
4307 ns_term_shutdown (int sig)
4309 [[NSUserDefaults standardUserDefaults] synchronize];
4311 /* code not reached in emacs.c after this is called by shut_down_emacs: */
4312 if (STRINGP (Vauto_save_list_file_name))
4313 unlink (SSDATA (Vauto_save_list_file_name));
4315 if (sig == 0 || sig == SIGTERM)
4317 [NSApp terminate: NSApp];
4319 else // force a stack trace to happen
4326 /* ==========================================================================
4328 EmacsApp implementation
4330 ========================================================================== */
4333 @implementation EmacsApp
4335 - (void)logNotification: (NSNotification *)notification
4337 const char *name = [[notification name] UTF8String];
4338 if (!strstr (name, "Update") && !strstr (name, "NSMenu")
4339 && !strstr (name, "WindowNumber"))
4340 NSLog (@"notification: '%@'", [notification name]);
4344 - (void)sendEvent: (NSEvent *)theEvent
4345 /* --------------------------------------------------------------------------
4346 Called when NSApp is running for each event received. Used to stop
4347 the loop when we choose, since there's no way to just run one iteration.
4348 -------------------------------------------------------------------------- */
4350 int type = [theEvent type];
4351 NSWindow *window = [theEvent window];
4353 /* NSTRACE (sendEvent); */
4354 /*fprintf (stderr, "received event of type %d\t%d\n", type);*/
4356 #ifdef NS_IMPL_GNUSTEP
4357 // Keyboard events aren't propagated to file dialogs for some reason.
4358 if ([NSApp modalWindow] != nil &&
4359 (type == NSKeyDown || type == NSKeyUp || type == NSFlagsChanged))
4361 [[NSApp modalWindow] sendEvent: theEvent];
4366 if (type == NSApplicationDefined)
4368 switch ([theEvent data2])
4370 #ifdef NS_IMPL_COCOA
4371 case NSAPP_DATA2_RUNASSCRIPT:
4376 case NSAPP_DATA2_RUNFILEDIALOG:
4377 ns_run_file_dialog ();
4383 if (type == NSCursorUpdate && window == nil)
4385 fprintf (stderr, "Dropping external cursor update event.\n");
4389 if (type == NSApplicationDefined)
4391 /* Events posted by ns_send_appdefined interrupt the run loop here.
4392 But, if a modal window is up, an appdefined can still come through,
4393 (e.g., from a makeKeyWindow event) but stopping self also stops the
4394 modal loop. Just defer it until later. */
4395 if ([NSApp modalWindow] == nil)
4397 last_appdefined_event_data = [theEvent data1];
4402 send_appdefined = YES;
4407 #ifdef NS_IMPL_COCOA
4408 /* If no dialog and none of our frames have focus and it is a move, skip it.
4409 It is a mouse move in an auxiliary menu, i.e. on the top right on OSX,
4410 such as Wifi, sound, date or similar.
4411 This prevents "spooky" highlighting in the frame under the menu. */
4412 if (type == NSMouseMoved && [NSApp modalWindow] == nil)
4414 struct ns_display_info *di;
4415 BOOL has_focus = NO;
4416 for (di = x_display_list; ! has_focus && di; di = di->next)
4417 has_focus = di->x_focus_frame != 0;
4423 [super sendEvent: theEvent];
4427 - (void)showPreferencesWindow: (id)sender
4429 struct frame *emacsframe = SELECTED_FRAME ();
4430 NSEvent *theEvent = [NSApp currentEvent];
4434 emacs_event->kind = NS_NONKEY_EVENT;
4435 emacs_event->code = KEY_NS_SHOW_PREFS;
4436 emacs_event->modifiers = 0;
4437 EV_TRAILER (theEvent);
4441 - (void)newFrame: (id)sender
4443 struct frame *emacsframe = SELECTED_FRAME ();
4444 NSEvent *theEvent = [NSApp currentEvent];
4448 emacs_event->kind = NS_NONKEY_EVENT;
4449 emacs_event->code = KEY_NS_NEW_FRAME;
4450 emacs_event->modifiers = 0;
4451 EV_TRAILER (theEvent);
4455 /* Open a file (used by below, after going into queue read by ns_read_socket) */
4456 - (BOOL) openFile: (NSString *)fileName
4458 struct frame *emacsframe = SELECTED_FRAME ();
4459 NSEvent *theEvent = [NSApp currentEvent];
4464 emacs_event->kind = NS_NONKEY_EVENT;
4465 emacs_event->code = KEY_NS_OPEN_FILE_LINE;
4466 ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
4467 ns_input_line = Qnil; /* can be start or cons start,end */
4468 emacs_event->modifiers =0;
4469 EV_TRAILER (theEvent);
4475 /* **************************************************************************
4477 EmacsApp delegate implementation
4479 ************************************************************************** */
4481 - (void)applicationDidFinishLaunching: (NSNotification *)notification
4482 /* --------------------------------------------------------------------------
4483 When application is loaded, terminate event loop in ns_term_init
4484 -------------------------------------------------------------------------- */
4486 NSTRACE (applicationDidFinishLaunching);
4487 [NSApp setServicesProvider: NSApp];
4488 ns_send_appdefined (-2);
4492 /* Termination sequences:
4495 MenuBar | File | Exit:
4496 Select Quit from App menubar:
4498 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
4501 Select Quit from Dock menu:
4504 Cancel -> Nothing else
4508 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
4513 - (void) terminate: (id)sender
4515 struct frame *emacsframe = SELECTED_FRAME ();
4520 emacs_event->kind = NS_NONKEY_EVENT;
4521 emacs_event->code = KEY_NS_POWER_OFF;
4522 emacs_event->arg = Qt; /* mark as non-key event */
4523 EV_TRAILER ((id)nil);
4527 - (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
4531 if (NILP (ns_confirm_quit)) // || ns_shutdown_properly --> TO DO
4532 return NSTerminateNow;
4534 ret = NSRunAlertPanel(ns_app_name,
4535 @"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?",
4536 @"Save Buffers and Exit", @"Cancel", nil);
4538 if (ret == NSAlertDefaultReturn)
4539 return NSTerminateNow;
4540 else if (ret == NSAlertAlternateReturn)
4541 return NSTerminateCancel;
4542 return NSTerminateNow; /* just in case */
4546 not_in_argv (NSString *arg)
4549 const char *a = [arg UTF8String];
4550 for (k = 1; k < initial_argc; ++k)
4551 if (strcmp (a, initial_argv[k]) == 0) return 0;
4555 /* Notification from the Workspace to open a file */
4556 - (BOOL)application: sender openFile: (NSString *)file
4558 if (ns_do_open_file || not_in_argv (file))
4559 [ns_pending_files addObject: file];
4564 /* Open a file as a temporary file */
4565 - (BOOL)application: sender openTempFile: (NSString *)file
4567 if (ns_do_open_file || not_in_argv (file))
4568 [ns_pending_files addObject: file];
4573 /* Notification from the Workspace to open a file noninteractively (?) */
4574 - (BOOL)application: sender openFileWithoutUI: (NSString *)file
4576 if (ns_do_open_file || not_in_argv (file))
4577 [ns_pending_files addObject: file];
4581 /* Notification from the Workspace to open multiple files */
4582 - (void)application: sender openFiles: (NSArray *)fileList
4584 NSEnumerator *files = [fileList objectEnumerator];
4586 /* Don't open files from the command line unconditionally,
4587 Cocoa parses the command line wrong, --option value tries to open value
4588 if --option is the last option. */
4589 while ((file = [files nextObject]) != nil)
4590 if (ns_do_open_file || not_in_argv (file))
4591 [ns_pending_files addObject: file];
4593 [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
4598 /* Handle dock menu requests. */
4599 - (NSMenu *)applicationDockMenu: (NSApplication *) sender
4605 /* TODO: these may help w/IO switching btwn terminal and NSApp */
4606 - (void)applicationWillBecomeActive: (NSNotification *)notification
4608 //ns_app_active=YES;
4610 - (void)applicationDidBecomeActive: (NSNotification *)notification
4612 NSTRACE (applicationDidBecomeActive);
4614 //ns_app_active=YES;
4616 ns_update_auto_hide_menu_bar ();
4617 // No constraining takes place when the application is not active.
4618 ns_constrain_all_frames ();
4620 - (void)applicationDidResignActive: (NSNotification *)notification
4623 ns_send_appdefined (-1);
4628 /* ==========================================================================
4630 EmacsApp aux handlers for managing event loop
4632 ========================================================================== */
4635 - (void)timeout_handler: (NSTimer *)timedEntry
4636 /* --------------------------------------------------------------------------
4637 The timeout specified to ns_select has passed.
4638 -------------------------------------------------------------------------- */
4640 /*NSTRACE (timeout_handler); */
4641 ns_send_appdefined (-2);
4644 #ifdef NS_IMPL_GNUSTEP
4645 - (void)sendFromMainThread:(id)unused
4647 ns_send_appdefined (nextappdefined);
4651 - (void)fd_handler:(id)unused
4652 /* --------------------------------------------------------------------------
4653 Check data waiting on file descriptors and terminate if so
4654 -------------------------------------------------------------------------- */
4657 int waiting = 1, nfds;
4660 fd_set readfds, writefds, *wfds;
4661 struct timespec timeout, *tmo;
4662 NSAutoreleasePool *pool = nil;
4664 /* NSTRACE (fd_handler); */
4669 pool = [[NSAutoreleasePool alloc] init];
4675 FD_SET (selfds[0], &fds);
4676 result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
4677 if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
4682 pthread_mutex_lock (&select_mutex);
4685 if (select_valid & SELECT_HAVE_READ)
4686 readfds = select_readfds;
4690 if (select_valid & SELECT_HAVE_WRITE)
4692 writefds = select_writefds;
4697 if (select_valid & SELECT_HAVE_TMO)
4699 timeout = select_timeout;
4705 pthread_mutex_unlock (&select_mutex);
4707 FD_SET (selfds[0], &readfds);
4708 if (selfds[0] >= nfds) nfds = selfds[0]+1;
4710 result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL);
4713 ns_send_appdefined (-2);
4714 else if (result > 0)
4716 if (FD_ISSET (selfds[0], &readfds))
4718 if (read (selfds[0], &c, 1) == 1 && c == 's')
4723 pthread_mutex_lock (&select_mutex);
4724 if (select_valid & SELECT_HAVE_READ)
4725 select_readfds = readfds;
4726 if (select_valid & SELECT_HAVE_WRITE)
4727 select_writefds = writefds;
4728 if (select_valid & SELECT_HAVE_TMO)
4729 select_timeout = timeout;
4730 pthread_mutex_unlock (&select_mutex);
4732 ns_send_appdefined (result);
4742 /* ==========================================================================
4746 ========================================================================== */
4748 /* called from system: queue for next pass through event loop */
4749 - (void)requestService: (NSPasteboard *)pboard
4750 userData: (NSString *)userData
4751 error: (NSString **)error
4753 [ns_pending_service_names addObject: userData];
4754 [ns_pending_service_args addObject: [NSString stringWithUTF8String:
4755 SSDATA (ns_string_from_pasteboard (pboard))]];
4759 /* called from ns_read_socket to clear queue */
4760 - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
4762 struct frame *emacsframe = SELECTED_FRAME ();
4763 NSEvent *theEvent = [NSApp currentEvent];
4768 emacs_event->kind = NS_NONKEY_EVENT;
4769 emacs_event->code = KEY_NS_SPI_SERVICE_CALL;
4770 ns_input_spi_name = build_string ([name UTF8String]);
4771 ns_input_spi_arg = build_string ([arg UTF8String]);
4772 emacs_event->modifiers = EV_MODIFIERS (theEvent);
4773 EV_TRAILER (theEvent);
4783 /* ==========================================================================
4785 EmacsView implementation
4787 ========================================================================== */
4790 @implementation EmacsView
4792 /* needed to inform when window closed from LISP */
4793 - (void) setWindowClosing: (BOOL)closing
4795 windowClosing = closing;
4801 NSTRACE (EmacsView_dealloc);
4803 if (fs_state == FULLSCREEN_BOTH)
4804 [nonfs_window release];
4809 /* called on font panel selection */
4810 - (void)changeFont: (id)sender
4812 NSEvent *e =[[self window] currentEvent];
4813 struct face *face =FRAME_DEFAULT_FACE (emacsframe);
4817 NSTRACE (changeFont);
4821 if ((newFont = [sender convertFont:
4822 ((struct nsfont_info *)face->font)->nsfont]))
4824 SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
4826 emacs_event->kind = NS_NONKEY_EVENT;
4827 emacs_event->modifiers = 0;
4828 emacs_event->code = KEY_NS_CHANGE_FONT;
4830 size = [newFont pointSize];
4831 ns_input_fontsize = make_number (lrint (size));
4832 ns_input_font = build_string ([[newFont familyName] UTF8String]);
4838 - (BOOL)acceptsFirstResponder
4840 NSTRACE (acceptsFirstResponder);
4845 - (void)resetCursorRects
4847 NSRect visible = [self visibleRect];
4848 NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
4849 NSTRACE (resetCursorRects);
4851 if (currentCursor == nil)
4852 currentCursor = [NSCursor arrowCursor];
4854 if (!NSIsEmptyRect (visible))
4855 [self addCursorRect: visible cursor: currentCursor];
4856 [currentCursor setOnMouseEntered: YES];
4861 /*****************************************************************************/
4862 /* Keyboard handling. */
4865 - (void)keyDown: (NSEvent *)theEvent
4867 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
4869 unsigned fnKeysym = 0;
4870 static NSMutableArray *nsEvArray;
4871 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
4872 static BOOL firstTime = YES;
4875 unsigned int flags = [theEvent modifierFlags];
4879 /* Rhapsody and OS X give up and down events for the arrow keys */
4880 if (ns_fake_keydown == YES)
4881 ns_fake_keydown = NO;
4882 else if ([theEvent type] != NSKeyDown)
4888 if (![[self window] isKeyWindow]
4889 && [[theEvent window] isKindOfClass: [EmacsWindow class]]
4890 /* we must avoid an infinite loop here. */
4891 && (EmacsView *)[[theEvent window] delegate] != self)
4893 /* XXX: There is an occasional condition in which, when Emacs display
4894 updates a different frame from the current one, and temporarily
4895 selects it, then processes some interrupt-driven input
4896 (dispnew.c:3878), OS will send the event to the correct NSWindow, but
4897 for some reason that window has its first responder set to the NSView
4898 most recently updated (I guess), which is not the correct one. */
4899 [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
4903 if (nsEvArray == nil)
4904 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
4906 [NSCursor setHiddenUntilMouseMoves: YES];
4908 if (hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
4910 clear_mouse_face (hlinfo);
4911 hlinfo->mouse_face_hidden = 1;
4914 if (!processingCompose)
4916 /* When using screen sharing, no left or right information is sent,
4917 so use Left key in those cases. */
4918 int is_left_key, is_right_key;
4920 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
4921 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
4923 /* (Carbon way: [theEvent keyCode]) */
4925 /* is it a "function key"? */
4926 fnKeysym = (code < 0x00ff && (flags&NSNumericPadKeyMask))
4927 ? ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask)
4928 : ns_convert_key (code);
4932 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
4933 because Emacs treats Delete and KP-Delete same (in simple.el). */
4934 if ((fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33)
4935 #ifdef NS_IMPL_GNUSTEP
4936 /* GNUstep uses incompatible keycodes, even for those that are
4937 supposed to be hardware independent. Just check for delete.
4938 Keypad delete does not have keysym 0xFFFF.
4939 See http://savannah.gnu.org/bugs/?25395
4941 || (fnKeysym == 0xFFFF && code == 127)
4944 code = 0xFF08; /* backspace */
4949 /* are there modifiers? */
4950 emacs_event->modifiers = 0;
4952 if (flags & NSHelpKeyMask)
4953 emacs_event->modifiers |= hyper_modifier;
4955 if (flags & NSShiftKeyMask)
4956 emacs_event->modifiers |= shift_modifier;
4958 is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask;
4959 is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
4960 || (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask);
4963 emacs_event->modifiers |= parse_solitary_modifier
4964 (EQ (ns_right_command_modifier, Qleft)
4965 ? ns_command_modifier
4966 : ns_right_command_modifier);
4970 emacs_event->modifiers |= parse_solitary_modifier
4971 (ns_command_modifier);
4973 /* if super (default), take input manager's word so things like
4974 dvorak / qwerty layout work */
4975 if (EQ (ns_command_modifier, Qsuper)
4977 && [[theEvent characters] length] != 0)
4979 /* XXX: the code we get will be unshifted, so if we have
4980 a shift modifier, must convert ourselves */
4981 if (!(flags & NSShiftKeyMask))
4982 code = [[theEvent characters] characterAtIndex: 0];
4984 /* this is ugly and also requires linking w/Carbon framework
4985 (for LMGetKbdType) so for now leave this rare (?) case
4986 undealt with.. in future look into CGEvent methods */
4989 long smv = GetScriptManagerVariable (smKeyScript);
4990 Handle uchrHandle = GetResource
4991 ('uchr', GetScriptVariable (smv, smScriptKeys));
4993 UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle,
4994 [[theEvent characters] characterAtIndex: 0],
4995 kUCKeyActionDisplay,
4996 (flags & ~NSCommandKeyMask) >> 8,
4997 LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask,
4998 &dummy, 1, &dummy, &code);
5005 is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask;
5006 is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask
5007 || (! is_right_key && (flags & NSControlKeyMask) == NSControlKeyMask);
5010 emacs_event->modifiers |= parse_solitary_modifier
5011 (EQ (ns_right_control_modifier, Qleft)
5012 ? ns_control_modifier
5013 : ns_right_control_modifier);
5016 emacs_event->modifiers |= parse_solitary_modifier
5017 (ns_control_modifier);
5019 if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
5020 emacs_event->modifiers |=
5021 parse_solitary_modifier (ns_function_modifier);
5023 left_is_none = NILP (ns_alternate_modifier)
5024 || EQ (ns_alternate_modifier, Qnone);
5026 is_right_key = (flags & NSRightAlternateKeyMask)
5027 == NSRightAlternateKeyMask;
5028 is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
5030 && (flags & NSAlternateKeyMask) == NSAlternateKeyMask);
5034 if ((NILP (ns_right_alternate_modifier)
5035 || EQ (ns_right_alternate_modifier, Qnone)
5036 || (EQ (ns_right_alternate_modifier, Qleft) && left_is_none))
5038 { /* accept pre-interp alt comb */
5039 if ([[theEvent characters] length] > 0)
5040 code = [[theEvent characters] characterAtIndex: 0];
5041 /*HACK: clear lone shift modifier to stop next if from firing */
5042 if (emacs_event->modifiers == shift_modifier)
5043 emacs_event->modifiers = 0;
5046 emacs_event->modifiers |= parse_solitary_modifier
5047 (EQ (ns_right_alternate_modifier, Qleft)
5048 ? ns_alternate_modifier
5049 : ns_right_alternate_modifier);
5052 if (is_left_key) /* default = meta */
5054 if (left_is_none && !fnKeysym)
5055 { /* accept pre-interp alt comb */
5056 if ([[theEvent characters] length] > 0)
5057 code = [[theEvent characters] characterAtIndex: 0];
5058 /*HACK: clear lone shift modifier to stop next if from firing */
5059 if (emacs_event->modifiers == shift_modifier)
5060 emacs_event->modifiers = 0;
5063 emacs_event->modifiers |=
5064 parse_solitary_modifier (ns_alternate_modifier);
5068 fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",
5069 code, fnKeysym, flags, emacs_event->modifiers);
5071 /* if it was a function key or had modifiers, pass it directly to emacs */
5072 if (fnKeysym || (emacs_event->modifiers
5073 && (emacs_event->modifiers != shift_modifier)
5074 && [[theEvent charactersIgnoringModifiers] length] > 0))
5075 /*[[theEvent characters] length] */
5077 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5079 code |= (1<<28)|(3<<16);
5080 else if (code == 0x7f)
5081 code |= (1<<28)|(3<<16);
5083 emacs_event->kind = code > 0xFF
5084 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5086 emacs_event->code = code;
5087 EV_TRAILER (theEvent);
5088 processingCompose = NO;
5094 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
5095 /* if we get here we should send the key for input manager processing */
5096 /* Disable warning, there is nothing a user can do about it anyway, and
5097 it does not seem to matter. */
5099 if (firstTime && [[NSInputManager currentInputManager]
5100 wantsToDelayTextChangeNotifications] == NO)
5102 "Emacs: WARNING: TextInput mgr wants marked text to be permanent!\n");
5106 if (NS_KEYLOG && !processingCompose)
5107 fprintf (stderr, "keyDown: Begin compose sequence.\n");
5109 processingCompose = YES;
5110 [nsEvArray addObject: theEvent];
5111 [self interpretKeyEvents: nsEvArray];
5112 [nsEvArray removeObject: theEvent];
5116 #ifdef NS_IMPL_COCOA
5117 /* Needed to pick up Ctrl-tab and possibly other events that OS X has
5118 decided not to send key-down for.
5119 See http://osdir.com/ml/editors.vim.mac/2007-10/msg00141.html
5120 This only applies on Tiger and earlier.
5121 If it matches one of these, send it on to keyDown. */
5122 -(void)keyUp: (NSEvent *)theEvent
5124 int flags = [theEvent modifierFlags];
5125 int code = [theEvent keyCode];
5126 if (floor (NSAppKitVersionNumber) <= 824 /*NSAppKitVersionNumber10_4*/ &&
5127 code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask))
5130 fprintf (stderr, "keyUp: passed test");
5131 ns_fake_keydown = YES;
5132 [self keyDown: theEvent];
5138 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
5141 /* <NSTextInput>: called when done composing;
5142 NOTE: also called when we delete over working text, followed immed.
5143 by doCommandBySelector: deleteBackward: */
5144 - (void)insertText: (id)aString
5147 int len = [(NSString *)aString length];
5151 NSLog (@"insertText '%@'\tlen = %d", aString, len);
5152 processingCompose = NO;
5157 /* first, clear any working text */
5158 if (workingText != nil)
5159 [self deleteWorkingText];
5161 /* now insert the string as keystrokes */
5162 for (i =0; i<len; i++)
5164 code = [aString characterAtIndex: i];
5165 /* TODO: still need this? */
5167 code = '~'; /* 0x7E */
5168 if (code != 32) /* Space */
5169 emacs_event->modifiers = 0;
5171 = code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5172 emacs_event->code = code;
5173 EV_TRAILER ((id)nil);
5178 /* <NSTextInput>: inserts display of composing characters */
5179 - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
5181 NSString *str = [aString respondsToSelector: @selector (string)] ?
5182 [aString string] : aString;
5184 NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
5185 selRange.length, selRange.location);
5187 if (workingText != nil)
5188 [self deleteWorkingText];
5189 if ([str length] == 0)
5195 processingCompose = YES;
5196 workingText = [str copy];
5197 ns_working_text = build_string ([workingText UTF8String]);
5199 emacs_event->kind = NS_TEXT_EVENT;
5200 emacs_event->code = KEY_NS_PUT_WORKING_TEXT;
5201 EV_TRAILER ((id)nil);
5205 /* delete display of composing characters [not in <NSTextInput>] */
5206 - (void)deleteWorkingText
5208 if (workingText == nil)
5211 NSLog(@"deleteWorkingText len =%d\n", [workingText length]);
5212 [workingText release];
5214 processingCompose = NO;
5219 emacs_event->kind = NS_TEXT_EVENT;
5220 emacs_event->code = KEY_NS_UNPUT_WORKING_TEXT;
5221 EV_TRAILER ((id)nil);
5225 - (BOOL)hasMarkedText
5227 return workingText != nil;
5231 - (NSRange)markedRange
5233 NSRange rng = workingText != nil
5234 ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
5236 NSLog (@"markedRange request");
5244 NSLog (@"unmark (accept) text");
5245 [self deleteWorkingText];
5246 processingCompose = NO;
5250 /* used to position char selection windows, etc. */
5251 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
5255 struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
5257 NSLog (@"firstRectForCharRange request");
5259 rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
5260 rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
5261 pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x);
5262 pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y
5263 +FRAME_LINE_HEIGHT (emacsframe));
5265 pt = [self convertPoint: pt toView: nil];
5266 pt = [[self window] convertBaseToScreen: pt];
5272 - (NSInteger)conversationIdentifier
5274 return (NSInteger)self;
5278 - (void)doCommandBySelector: (SEL)aSelector
5281 NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
5283 processingCompose = NO;
5284 if (aSelector == @selector (deleteBackward:))
5286 /* happens when user backspaces over an ongoing composition:
5287 throw a 'delete' into the event queue */
5290 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5291 emacs_event->code = 0xFF08;
5292 EV_TRAILER ((id)nil);
5296 - (NSArray *)validAttributesForMarkedText
5298 static NSArray *arr = nil;
5299 if (arr == nil) arr = [NSArray new];
5300 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
5304 - (NSRange)selectedRange
5307 NSLog (@"selectedRange request");
5308 return NSMakeRange (NSNotFound, 0);
5311 #if defined (NS_IMPL_COCOA) || GNUSTEP_GUI_MAJOR_VERSION > 0 || \
5312 GNUSTEP_GUI_MINOR_VERSION > 22
5313 - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
5315 - (unsigned int)characterIndexForPoint: (NSPoint)thePoint
5319 NSLog (@"characterIndexForPoint request");
5323 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
5325 static NSAttributedString *str = nil;
5326 if (str == nil) str = [NSAttributedString new];
5328 NSLog (@"attributedSubstringFromRange request");
5332 /* End <NSTextInput> impl. */
5333 /*****************************************************************************/
5336 /* This is what happens when the user presses a mouse button. */
5337 - (void)mouseDown: (NSEvent *)theEvent
5339 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
5341 NSTRACE (mouseDown);
5343 [self deleteWorkingText];
5348 last_mouse_frame = emacsframe;
5349 /* appears to be needed to prevent spurious movement events generated on
5351 last_mouse_frame->mouse_moved = 0;
5353 if ([theEvent type] == NSScrollWheel)
5355 CGFloat delta = [theEvent deltaY];
5356 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
5359 emacs_event->kind = WHEEL_EVENT;
5360 emacs_event->code = 0;
5361 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
5362 ((delta > 0) ? up_modifier : down_modifier);
5366 emacs_event->kind = MOUSE_CLICK_EVENT;
5367 emacs_event->code = EV_BUTTON (theEvent);
5368 emacs_event->modifiers = EV_MODIFIERS (theEvent)
5369 | EV_UDMODIFIERS (theEvent);
5371 XSETINT (emacs_event->x, lrint (p.x));
5372 XSETINT (emacs_event->y, lrint (p.y));
5373 EV_TRAILER (theEvent);
5377 - (void)rightMouseDown: (NSEvent *)theEvent
5379 NSTRACE (rightMouseDown);
5380 [self mouseDown: theEvent];
5384 - (void)otherMouseDown: (NSEvent *)theEvent
5386 NSTRACE (otherMouseDown);
5387 [self mouseDown: theEvent];
5391 - (void)mouseUp: (NSEvent *)theEvent
5394 [self mouseDown: theEvent];
5398 - (void)rightMouseUp: (NSEvent *)theEvent
5400 NSTRACE (rightMouseUp);
5401 [self mouseDown: theEvent];
5405 - (void)otherMouseUp: (NSEvent *)theEvent
5407 NSTRACE (otherMouseUp);
5408 [self mouseDown: theEvent];
5412 - (void) scrollWheel: (NSEvent *)theEvent
5414 NSTRACE (scrollWheel);
5415 [self mouseDown: theEvent];
5419 /* Tell emacs the mouse has moved. */
5420 - (void)mouseMoved: (NSEvent *)e
5422 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
5425 // NSTRACE (mouseMoved);
5427 last_mouse_movement_time = EV_TIMESTAMP (e);
5428 last_mouse_motion_position
5429 = [self convertPoint: [e locationInWindow] fromView: nil];
5431 /* update any mouse face */
5432 if (hlinfo->mouse_face_hidden)
5434 hlinfo->mouse_face_hidden = 0;
5435 clear_mouse_face (hlinfo);
5438 /* tooltip handling */
5439 previous_help_echo_string = help_echo_string;
5440 help_echo_string = Qnil;
5442 if (!NILP (Vmouse_autoselect_window))
5444 NSTRACE (mouse_autoselect_window);
5445 static Lisp_Object last_mouse_window;
5446 Lisp_Object window = window_from_coordinates
5447 (emacsframe, last_mouse_motion_position.x,
5448 last_mouse_motion_position.y, 0, 0);
5450 if (WINDOWP (window)
5451 && !EQ (window, last_mouse_window)
5452 && !EQ (window, selected_window)
5453 && (focus_follows_mouse
5454 || (EQ (XWINDOW (window)->frame,
5455 XWINDOW (selected_window)->frame))))
5457 NSTRACE (in_window);
5458 emacs_event->kind = SELECT_WINDOW_EVENT;
5459 emacs_event->frame_or_window = window;
5462 /* Remember the last window where we saw the mouse. */
5463 last_mouse_window = window;
5466 if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x,
5467 last_mouse_motion_position.y))
5468 help_echo_string = previous_help_echo_string;
5470 XSETFRAME (frame, emacsframe);
5471 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
5473 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
5474 (note_mouse_highlight), which is called through the
5475 note_mouse_movement () call above */
5476 gen_help_event (help_echo_string, frame, help_echo_window,
5477 help_echo_object, help_echo_pos);
5481 help_echo_string = Qnil;
5482 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
5485 if (emacsframe->mouse_moved && send_appdefined)
5486 ns_send_appdefined (-1);
5490 - (void)mouseDragged: (NSEvent *)e
5492 NSTRACE (mouseDragged);
5493 [self mouseMoved: e];
5497 - (void)rightMouseDragged: (NSEvent *)e
5499 NSTRACE (rightMouseDragged);
5500 [self mouseMoved: e];
5504 - (void)otherMouseDragged: (NSEvent *)e
5506 NSTRACE (otherMouseDragged);
5507 [self mouseMoved: e];
5511 - (BOOL)windowShouldClose: (id)sender
5513 NSEvent *e =[[self window] currentEvent];
5515 NSTRACE (windowShouldClose);
5516 windowClosing = YES;
5519 emacs_event->kind = DELETE_WINDOW_EVENT;
5520 emacs_event->modifiers = 0;
5521 emacs_event->code = 0;
5523 /* Don't close this window, let this be done from lisp code. */
5527 - (void) updateFrameSize: (BOOL) delay;
5529 NSWindow *window = [self window];
5530 NSRect wr = [window frame];
5533 #ifdef NS_IMPL_GNUSTEP
5537 int oldc = cols, oldr = rows;
5538 int oldw = FRAME_PIXEL_WIDTH (emacsframe),
5539 oldh = FRAME_PIXEL_HEIGHT (emacsframe);
5542 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + gsextra);
5544 if (cols < MINWIDTH)
5547 if (! [self isFullscreen])
5549 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5550 + FRAME_TOOLBAR_HEIGHT (emacsframe) - gsextra;
5553 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, wr.size.height - extra);
5555 if (rows < MINHEIGHT)
5558 neww = (int)wr.size.width - emacsframe->border_width;
5559 newh = (int)wr.size.height - extra;
5561 if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
5563 NSView *view = FRAME_NS_VIEW (emacsframe);
5564 NSWindow *win = [view window];
5565 NSSize sz = [win resizeIncrements];
5567 FRAME_PIXEL_WIDTH (emacsframe) = neww;
5568 FRAME_PIXEL_HEIGHT (emacsframe) = newh;
5569 change_frame_size (emacsframe, rows, cols, 0, delay, 0);
5570 SET_FRAME_GARBAGED (emacsframe);
5571 cancel_mouse_face (emacsframe);
5573 // Did resize increments change because of a font change?
5574 if (sz.width != FRAME_COLUMN_WIDTH (emacsframe) ||
5575 sz.height != FRAME_LINE_HEIGHT (emacsframe))
5577 sz.width = FRAME_COLUMN_WIDTH (emacsframe);
5578 sz.height = FRAME_LINE_HEIGHT (emacsframe);
5579 [win setResizeIncrements: sz];
5582 [view setFrame: NSMakeRect (0, 0, neww, newh)];
5583 [self windowDidMove:nil]; // Update top/left.
5587 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
5588 /* normalize frame to gridded text size */
5592 #ifdef NS_IMPL_GNUSTEP
5596 NSTRACE (windowWillResize);
5597 /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
5599 if (fs_state == FULLSCREEN_MAXIMIZED
5600 && (maximized_width != (int)frameSize.width
5601 || maximized_height != (int)frameSize.height))
5602 [self setFSValue: FULLSCREEN_NONE];
5603 else if (fs_state == FULLSCREEN_WIDTH
5604 && maximized_width != (int)frameSize.width)
5605 [self setFSValue: FULLSCREEN_NONE];
5606 else if (fs_state == FULLSCREEN_HEIGHT
5607 && maximized_height != (int)frameSize.height)
5608 [self setFSValue: FULLSCREEN_NONE];
5609 if (fs_state == FULLSCREEN_NONE)
5610 maximized_width = maximized_height = -1;
5612 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
5613 frameSize.width + gsextra);
5614 if (cols < MINWIDTH)
5617 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe,
5618 frameSize.height - extra);
5619 if (rows < MINHEIGHT)
5621 #ifdef NS_IMPL_COCOA
5623 /* this sets window title to have size in it; the wm does this under GS */
5624 NSRect r = [[self window] frame];
5625 if (r.size.height == frameSize.height && r.size.width == frameSize.width)
5633 else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize)
5636 NSWindow *window = [self window];
5639 char *t = strdup ([[[self window] title] UTF8String]);
5640 char *pos = strstr (t, " — ");
5645 size_title = xmalloc (strlen (old_title) + 40);
5646 esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
5647 [window setTitle: [NSString stringWithUTF8String: size_title]];
5652 #endif /* NS_IMPL_COCOA */
5653 /*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */
5659 - (void)windowDidResize: (NSNotification *)notification
5661 if (! [self fsIsNative])
5663 NSWindow *theWindow = [notification object];
5664 /* We can get notification on the non-FS window when in
5666 if ([self window] != theWindow) return;
5669 #ifdef NS_IMPL_GNUSTEP
5670 NSWindow *theWindow = [notification object];
5672 /* In GNUstep, at least currently, it's possible to get a didResize
5673 without getting a willResize.. therefore we need to act as if we got
5674 the willResize now */
5675 NSSize sz = [theWindow frame].size;
5676 sz = [self windowWillResize: theWindow toSize: sz];
5677 #endif /* NS_IMPL_GNUSTEP */
5679 NSTRACE (windowDidResize);
5680 /*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */
5682 if (cols > 0 && rows > 0)
5684 [self updateFrameSize: YES];
5687 ns_send_appdefined (-1);
5690 #ifdef NS_IMPL_COCOA
5691 - (void)viewDidEndLiveResize
5693 [super viewDidEndLiveResize];
5696 [[self window] setTitle: [NSString stringWithUTF8String: old_title]];
5700 maximizing_resize = NO;
5702 #endif /* NS_IMPL_COCOA */
5705 - (void)windowDidBecomeKey: (NSNotification *)notification
5706 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5708 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
5709 struct frame *old_focus = dpyinfo->x_focus_frame;
5711 NSTRACE (windowDidBecomeKey);
5713 if (emacsframe != old_focus)
5714 dpyinfo->x_focus_frame = emacsframe;
5716 ns_frame_rehighlight (emacsframe);
5720 emacs_event->kind = FOCUS_IN_EVENT;
5721 EV_TRAILER ((id)nil);
5726 - (void)windowDidResignKey: (NSNotification *)notification
5727 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5729 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
5730 BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe;
5731 NSTRACE (windowDidResignKey);
5734 dpyinfo->x_focus_frame = 0;
5736 ns_frame_rehighlight (emacsframe);
5738 /* FIXME: for some reason needed on second and subsequent clicks away
5739 from sole-frame Emacs to get hollow box to show */
5740 if (!windowClosing && [[self window] isVisible] == YES)
5742 x_update_cursor (emacsframe, 1);
5743 x_set_frame_alpha (emacsframe);
5746 if (emacs_event && is_focus_frame)
5748 [self deleteWorkingText];
5749 emacs_event->kind = FOCUS_OUT_EVENT;
5750 EV_TRAILER ((id)nil);
5755 - (void)windowWillMiniaturize: sender
5757 NSTRACE (windowWillMiniaturize);
5773 - initFrameFromEmacs: (struct frame *)f
5782 NSTRACE (initFrameFromEmacs);
5785 processingCompose = NO;
5786 scrollbarsNeedingUpdate = 0;
5787 fs_state = FULLSCREEN_NONE;
5788 fs_before_fs = next_maximized = -1;
5789 #ifdef HAVE_NATIVE_FS
5790 fs_is_native = ns_use_native_fullscreen;
5794 maximized_width = maximized_height = -1;
5797 /*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
5799 ns_userRect = NSMakeRect (0, 0, 0, 0);
5800 r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
5801 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
5802 [self initWithFrame: r];
5803 [self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
5805 FRAME_NS_VIEW (f) = self;
5807 #ifdef NS_IMPL_COCOA
5809 maximizing_resize = NO;
5812 win = [[EmacsWindow alloc]
5813 initWithContentRect: r
5814 styleMask: (NSResizableWindowMask |
5815 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
5816 NSTitledWindowMask |
5818 NSMiniaturizableWindowMask |
5819 NSClosableWindowMask)
5820 backing: NSBackingStoreBuffered
5823 #ifdef HAVE_NATIVE_FS
5824 [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
5828 bwidth = f->border_width = wr.size.width - r.size.width;
5829 tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
5831 [win setAcceptsMouseMovedEvents: YES];
5832 [win setDelegate: self];
5833 [win useOptimizedDrawing: YES];
5835 sz.width = FRAME_COLUMN_WIDTH (f);
5836 sz.height = FRAME_LINE_HEIGHT (f);
5837 [win setResizeIncrements: sz];
5839 [[win contentView] addSubview: self];
5842 [self registerForDraggedTypes: ns_drag_types];
5845 name = [NSString stringWithUTF8String:
5846 NILP (tem) ? "Emacs" : SSDATA (tem)];
5847 [win setTitle: name];
5849 /* toolbar support */
5850 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
5851 [NSString stringWithFormat: @"Emacs Frame %d",
5853 [win setToolbar: toolbar];
5854 [toolbar setVisible: NO];
5855 #ifdef NS_IMPL_COCOA
5857 NSButton *toggleButton;
5858 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
5859 [toggleButton setTarget: self];
5860 [toggleButton setAction: @selector (toggleToolbar: )];
5863 FRAME_TOOLBAR_HEIGHT (f) = 0;
5867 [win setMiniwindowTitle:
5868 [NSString stringWithUTF8String: SSDATA (tem)]];
5871 NSScreen *screen = [win screen];
5874 [win setFrameTopLeftPoint: NSMakePoint
5875 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
5876 IN_BOUND (-SCREENMAX,
5877 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX))];
5880 [win makeFirstResponder: self];
5882 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
5883 (FRAME_DEFAULT_FACE (emacsframe)), emacsframe);
5884 [win setBackgroundColor: col];
5885 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
5886 [win setOpaque: NO];
5888 [self allocateGState];
5890 [NSApp registerServicesMenuSendTypes: ns_send_types
5898 - (void)windowDidMove: sender
5900 NSWindow *win = [self window];
5901 NSRect r = [win frame];
5902 NSArray *screens = [NSScreen screens];
5903 NSScreen *screen = [screens objectAtIndex: 0];
5905 NSTRACE (windowDidMove);
5907 if (!emacsframe->output_data.ns)
5911 emacsframe->left_pos = r.origin.x;
5912 emacsframe->top_pos =
5913 [screen frame].size.height - (r.origin.y + r.size.height);
5918 /* Called AFTER method below, but before our windowWillResize call there leads
5919 to windowDidResize -> x_set_window_size. Update emacs' notion of frame
5920 location so set_window_size moves the frame. */
5921 - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
5923 emacsframe->output_data.ns->zooming = 1;
5928 /* Override to do something slightly nonstandard, but nice. First click on
5929 zoom button will zoom vertically. Second will zoom completely. Third
5930 returns to original. */
5931 - (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
5932 defaultFrame:(NSRect)defaultFrame
5934 NSRect result = [sender frame];
5936 NSTRACE (windowWillUseStandardFrame);
5938 if (fs_before_fs != -1) /* Entering fullscreen */
5940 result = defaultFrame;
5942 else if (next_maximized == FULLSCREEN_HEIGHT
5943 || (next_maximized == -1
5944 && abs (defaultFrame.size.height - result.size.height)
5945 > FRAME_LINE_HEIGHT (emacsframe)))
5948 ns_userRect = result;
5949 maximized_height = result.size.height = defaultFrame.size.height;
5950 maximized_width = -1;
5951 result.origin.y = defaultFrame.origin.y;
5952 [self setFSValue: FULLSCREEN_HEIGHT];
5953 #ifdef NS_IMPL_COCOA
5954 maximizing_resize = YES;
5957 else if (next_maximized == FULLSCREEN_WIDTH)
5959 ns_userRect = result;
5960 maximized_width = result.size.width = defaultFrame.size.width;
5961 maximized_height = -1;
5962 result.origin.x = defaultFrame.origin.x;
5963 [self setFSValue: FULLSCREEN_WIDTH];
5965 else if (next_maximized == FULLSCREEN_MAXIMIZED
5966 || (next_maximized == -1
5967 && abs (defaultFrame.size.width - result.size.width)
5968 > FRAME_COLUMN_WIDTH (emacsframe)))
5970 result = defaultFrame; /* second click */
5971 maximized_width = result.size.width;
5972 maximized_height = result.size.height;
5973 [self setFSValue: FULLSCREEN_MAXIMIZED];
5974 #ifdef NS_IMPL_COCOA
5975 maximizing_resize = YES;
5981 result = ns_userRect.size.height ? ns_userRect : result;
5982 ns_userRect = NSMakeRect (0, 0, 0, 0);
5983 #ifdef NS_IMPL_COCOA
5984 maximizing_resize = fs_state != FULLSCREEN_NONE;
5986 [self setFSValue: FULLSCREEN_NONE];
5987 maximized_width = maximized_height = -1;
5990 if (fs_before_fs == -1) next_maximized = -1;
5991 [self windowWillResize: sender toSize: result.size];
5996 - (void)windowDidDeminiaturize: sender
5998 NSTRACE (windowDidDeminiaturize);
5999 if (!emacsframe->output_data.ns)
6002 SET_FRAME_ICONIFIED (emacsframe, 0);
6003 SET_FRAME_VISIBLE (emacsframe, 1);
6004 windows_or_buffers_changed++;
6008 emacs_event->kind = DEICONIFY_EVENT;
6009 EV_TRAILER ((id)nil);
6014 - (void)windowDidExpose: sender
6016 NSTRACE (windowDidExpose);
6017 if (!emacsframe->output_data.ns)
6020 SET_FRAME_VISIBLE (emacsframe, 1);
6021 SET_FRAME_GARBAGED (emacsframe);
6023 if (send_appdefined)
6024 ns_send_appdefined (-1);
6028 - (void)windowDidMiniaturize: sender
6030 NSTRACE (windowDidMiniaturize);
6031 if (!emacsframe->output_data.ns)
6034 SET_FRAME_ICONIFIED (emacsframe, 1);
6035 SET_FRAME_VISIBLE (emacsframe, 0);
6039 emacs_event->kind = ICONIFY_EVENT;
6040 EV_TRAILER ((id)nil);
6044 #ifdef HAVE_NATIVE_FS
6045 - (NSApplicationPresentationOptions)window:(NSWindow *)window
6046 willUseFullScreenPresentationOptions:
6047 (NSApplicationPresentationOptions)proposedOptions
6049 return proposedOptions|NSApplicationPresentationAutoHideToolbar;
6053 - (void)windowWillEnterFullScreen:(NSNotification *)notification
6055 fs_before_fs = fs_state;
6058 - (void)windowDidEnterFullScreen:(NSNotification *)notification
6060 [self setFSValue: FULLSCREEN_BOTH];
6061 if (! [self fsIsNative])
6063 [self windowDidBecomeKey:notification];
6064 [nonfs_window orderOut:self];
6066 else if (! FRAME_EXTERNAL_TOOL_BAR (emacsframe))
6067 [toolbar setVisible:NO];
6070 - (void)windowWillExitFullScreen:(NSNotification *)notification
6072 if (next_maximized != -1)
6073 fs_before_fs = next_maximized;
6076 - (void)windowDidExitFullScreen:(NSNotification *)notification
6078 [self setFSValue: fs_before_fs];
6080 #ifdef NS_IMPL_COCOA
6081 [self updateCollectionBehaviour];
6083 if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
6085 [toolbar setVisible:YES];
6086 update_frame_tool_bar (emacsframe);
6087 [self updateFrameSize:YES];
6088 [[self window] display];
6091 [toolbar setVisible:NO];
6093 if (next_maximized != -1)
6094 [[self window] performZoom:self];
6099 return fs_is_native;
6102 - (BOOL)isFullscreen
6104 if (! fs_is_native) return nonfs_window != nil;
6105 #ifdef HAVE_NATIVE_FS
6106 return ([[self window] styleMask] & NSFullScreenWindowMask) != 0;
6112 #ifdef HAVE_NATIVE_FS
6113 - (void)updateCollectionBehaviour
6115 if (! [self isFullscreen])
6117 NSWindow *win = [self window];
6118 NSWindowCollectionBehavior b = [win collectionBehavior];
6119 if (ns_use_native_fullscreen)
6120 b |= NSWindowCollectionBehaviorFullScreenPrimary;
6122 b &= ~NSWindowCollectionBehaviorFullScreenPrimary;
6124 [win setCollectionBehavior: b];
6125 fs_is_native = ns_use_native_fullscreen;
6130 - (void)toggleFullScreen: (id)sender
6141 #ifdef NS_IMPL_COCOA
6142 [[self window] toggleFullScreen:sender];
6148 onFirstScreen = [[w screen] isEqual:[[NSScreen screens] objectAtIndex:0]];
6151 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
6152 (FRAME_DEFAULT_FACE (f)),
6155 sz.width = FRAME_COLUMN_WIDTH (f);
6156 sz.height = FRAME_LINE_HEIGHT (f);
6158 if (fs_state != FULLSCREEN_BOTH)
6160 /* Hide dock and menubar if we are on the primary screen. */
6163 #if defined (NS_IMPL_COCOA) && \
6164 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
6165 NSApplicationPresentationOptions options
6166 = NSApplicationPresentationAutoHideDock
6167 | NSApplicationPresentationAutoHideMenuBar;
6169 [NSApp setPresentationOptions: options];
6171 [NSMenu setMenuBarVisible:NO];
6175 fw = [[EmacsFSWindow alloc]
6176 initWithContentRect:[w contentRectForFrameRect:wr]
6177 styleMask:NSBorderlessWindowMask
6178 backing:NSBackingStoreBuffered
6182 [fw setContentView:[w contentView]];
6183 [fw setTitle:[w title]];
6184 [fw setDelegate:self];
6185 [fw setAcceptsMouseMovedEvents: YES];
6186 [fw useOptimizedDrawing: YES];
6187 [fw setResizeIncrements: sz];
6188 [fw setBackgroundColor: col];
6189 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
6192 f->border_width = 0;
6193 FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
6194 tobar_height = FRAME_TOOLBAR_HEIGHT (f);
6195 FRAME_TOOLBAR_HEIGHT (f) = 0;
6199 [self windowWillEnterFullScreen:nil];
6200 [fw makeKeyAndOrderFront:NSApp];
6201 [fw makeFirstResponder:self];
6203 r = [fw frameRectForContentRect:[[fw screen] frame]];
6204 [fw setFrame: r display:YES animate:YES];
6205 [self windowDidEnterFullScreen:nil];
6216 #if defined (NS_IMPL_COCOA) && \
6217 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
6218 [NSApp setPresentationOptions: NSApplicationPresentationDefault];
6220 [NSMenu setMenuBarVisible:YES];
6224 [w setContentView:[fw contentView]];
6225 [w setResizeIncrements: sz];
6226 [w setBackgroundColor: col];
6227 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
6230 f->border_width = bwidth;
6231 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
6232 if (FRAME_EXTERNAL_TOOL_BAR (f))
6233 FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
6235 [self windowWillExitFullScreen:nil];
6236 [fw setFrame: [w frame] display:YES animate:YES];
6238 [w makeKeyAndOrderFront:NSApp];
6239 [self windowDidExitFullScreen:nil];
6240 [self updateFrameSize:YES];
6246 if (fs_state != emacsframe->want_fullscreen)
6248 if (fs_state == FULLSCREEN_BOTH)
6250 [self toggleFullScreen:self];
6253 switch (emacsframe->want_fullscreen)
6255 case FULLSCREEN_BOTH:
6256 [self toggleFullScreen:self];
6258 case FULLSCREEN_WIDTH:
6259 next_maximized = FULLSCREEN_WIDTH;
6260 if (fs_state != FULLSCREEN_BOTH)
6261 [[self window] performZoom:self];
6263 case FULLSCREEN_HEIGHT:
6264 next_maximized = FULLSCREEN_HEIGHT;
6265 if (fs_state != FULLSCREEN_BOTH)
6266 [[self window] performZoom:self];
6268 case FULLSCREEN_MAXIMIZED:
6269 next_maximized = FULLSCREEN_MAXIMIZED;
6270 if (fs_state != FULLSCREEN_BOTH)
6271 [[self window] performZoom:self];
6273 case FULLSCREEN_NONE:
6274 if (fs_state != FULLSCREEN_BOTH)
6276 next_maximized = FULLSCREEN_NONE;
6277 [[self window] performZoom:self];
6282 emacsframe->want_fullscreen = FULLSCREEN_NONE;
6287 - (void) setFSValue: (int)value
6289 Lisp_Object lval = Qnil;
6292 case FULLSCREEN_BOTH:
6295 case FULLSCREEN_WIDTH:
6298 case FULLSCREEN_HEIGHT:
6301 case FULLSCREEN_MAXIMIZED:
6305 store_frame_param (emacsframe, Qfullscreen, lval);
6309 - (void)mouseEntered: (NSEvent *)theEvent
6311 NSTRACE (mouseEntered);
6312 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
6316 - (void)mouseExited: (NSEvent *)theEvent
6318 Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL;
6320 NSTRACE (mouseExited);
6325 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
6327 if (emacsframe == hlinfo->mouse_face_mouse_frame)
6329 clear_mouse_face (hlinfo);
6330 hlinfo->mouse_face_mouse_frame = 0;
6338 if (context_menu_value == -1)
6339 context_menu_value = [sender tag];
6342 NSInteger tag = [sender tag];
6343 find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
6344 emacsframe->menu_bar_vector,
6348 ns_send_appdefined (-1);
6353 - (EmacsToolbar *)toolbar
6359 /* this gets called on toolbar button click */
6360 - toolbarClicked: (id)item
6363 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
6365 NSTRACE (toolbarClicked);
6370 /* send first event (for some reason two needed) */
6371 theEvent = [[self window] currentEvent];
6372 emacs_event->kind = TOOL_BAR_EVENT;
6373 XSETFRAME (emacs_event->arg, emacsframe);
6374 EV_TRAILER (theEvent);
6376 emacs_event->kind = TOOL_BAR_EVENT;
6377 /* XSETINT (emacs_event->code, 0); */
6378 emacs_event->arg = AREF (emacsframe->tool_bar_items,
6379 idx + TOOL_BAR_ITEM_KEY);
6380 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6381 EV_TRAILER (theEvent);
6386 - toggleToolbar: (id)sender
6391 emacs_event->kind = NS_NONKEY_EVENT;
6392 emacs_event->code = KEY_NS_TOGGLE_TOOLBAR;
6393 EV_TRAILER ((id)nil);
6398 - (void)drawRect: (NSRect)rect
6400 int x = NSMinX (rect), y = NSMinY (rect);
6401 int width = NSWidth (rect), height = NSHeight (rect);
6405 if (!emacsframe || !emacsframe->output_data.ns)
6408 ns_clear_frame_area (emacsframe, x, y, width, height);
6409 expose_frame (emacsframe, x, y, width, height);
6412 drawRect: may be called (at least in OS X 10.5) for invisible
6413 views as well for some reason. Thus, do not infer visibility
6416 emacsframe->async_visible = 1;
6417 emacsframe->async_iconified = 0;
6422 /* NSDraggingDestination protocol methods. Actually this is not really a
6423 protocol, but a category of Object. O well... */
6425 -(NSUInteger) draggingEntered: (id <NSDraggingInfo>) sender
6427 NSTRACE (draggingEntered);
6428 return NSDragOperationGeneric;
6432 -(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
6438 -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
6443 NSEvent *theEvent = [[self window] currentEvent];
6446 NSTRACE (performDragOperation);
6451 position = [self convertPoint: [sender draggingLocation] fromView: nil];
6452 x = lrint (position.x); y = lrint (position.y);
6454 pb = [sender draggingPasteboard];
6455 type = [pb availableTypeFromArray: ns_drag_types];
6460 else if ([type isEqualToString: NSFilenamesPboardType])
6463 NSEnumerator *fenum;
6466 if (!(files = [pb propertyListForType: type]))
6469 fenum = [files objectEnumerator];
6470 while ( (file = [fenum nextObject]) )
6472 emacs_event->kind = NS_NONKEY_EVENT;
6473 emacs_event->code = KEY_NS_DRAG_FILE;
6474 XSETINT (emacs_event->x, x);
6475 XSETINT (emacs_event->y, y);
6476 ns_input_file = append2 (ns_input_file,
6477 build_string ([file UTF8String]));
6478 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6479 EV_TRAILER (theEvent);
6483 else if ([type isEqualToString: NSURLPboardType])
6488 if (!(fileURL = [NSURL URLFromPasteboard: pb]) ||
6489 [fileURL isFileURL] == NO)
6492 file = [fileURL path];
6493 emacs_event->kind = NS_NONKEY_EVENT;
6494 emacs_event->code = KEY_NS_DRAG_FILE;
6495 XSETINT (emacs_event->x, x);
6496 XSETINT (emacs_event->y, y);
6497 ns_input_file = append2 (ns_input_file, build_string ([file UTF8String]));
6498 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6499 EV_TRAILER (theEvent);
6502 else if ([type isEqualToString: NSStringPboardType]
6503 || [type isEqualToString: NSTabularTextPboardType])
6507 if (! (data = [pb stringForType: type]))
6510 emacs_event->kind = NS_NONKEY_EVENT;
6511 emacs_event->code = KEY_NS_DRAG_TEXT;
6512 XSETINT (emacs_event->x, x);
6513 XSETINT (emacs_event->y, y);
6514 ns_input_text = build_string ([data UTF8String]);
6515 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6516 EV_TRAILER (theEvent);
6519 else if ([type isEqualToString: NSColorPboardType])
6521 NSColor *c = [NSColor colorFromPasteboard: pb];
6522 emacs_event->kind = NS_NONKEY_EVENT;
6523 emacs_event->code = KEY_NS_DRAG_COLOR;
6524 XSETINT (emacs_event->x, x);
6525 XSETINT (emacs_event->y, y);
6526 ns_input_color = ns_color_to_lisp (c);
6527 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6528 EV_TRAILER (theEvent);
6531 else if ([type isEqualToString: NSFontPboardType])
6533 /* impl based on GNUstep NSTextView.m */
6534 NSData *data = [pb dataForType: NSFontPboardType];
6535 NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data];
6536 NSFont *font = [dict objectForKey: NSFontAttributeName];
6542 emacs_event->kind = NS_NONKEY_EVENT;
6543 emacs_event->code = KEY_NS_CHANGE_FONT;
6544 XSETINT (emacs_event->x, x);
6545 XSETINT (emacs_event->y, y);
6546 ns_input_font = build_string ([[font fontName] UTF8String]);
6547 snprintf (fontSize, 10, "%f", [font pointSize]);
6548 ns_input_fontsize = build_string (fontSize);
6549 emacs_event->modifiers = EV_MODIFIERS (theEvent);
6550 EV_TRAILER (theEvent);
6555 error ("Invalid data type in dragging pasteboard.");
6561 - (id) validRequestorForSendType: (NSString *)typeSent
6562 returnType: (NSString *)typeReturned
6564 NSTRACE (validRequestorForSendType);
6565 if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound
6566 && typeReturned == nil)
6568 if (! NILP (ns_get_local_selection (QPRIMARY, QUTF8_STRING)))
6572 return [super validRequestorForSendType: typeSent
6573 returnType: typeReturned];
6577 /* The next two methods are part of NSServicesRequests informal protocol,
6578 supposedly called when a services menu item is chosen from this app.
6579 But this should not happen because we override the services menu with our
6580 own entries which call ns-perform-service.
6581 Nonetheless, it appeared to happen (under strange circumstances): bug#1435.
6582 So let's at least stub them out until further investigation can be done. */
6584 - (BOOL) readSelectionFromPasteboard: (NSPasteboard *)pb
6586 /* we could call ns_string_from_pasteboard(pboard) here but then it should
6587 be written into the buffer in place of the existing selection..
6588 ordinary service calls go through functions defined in ns-win.el */
6592 - (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types
6594 NSArray *typesDeclared;
6597 /* We only support NSStringPboardType */
6598 if ([types containsObject:NSStringPboardType] == NO) {
6602 val = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
6603 if (CONSP (val) && SYMBOLP (XCAR (val)))
6606 if (CONSP (val) && NILP (XCDR (val)))
6609 if (! STRINGP (val))
6612 typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
6613 [pb declareTypes:typesDeclared owner:nil];
6614 ns_string_to_pasteboard (pb, val);
6619 /* setMini =YES means set from internal (gives a finder icon), NO means set nil
6620 (gives a miniaturized version of the window); currently we use the latter for
6621 frames whose active buffer doesn't correspond to any file
6622 (e.g., '*scratch*') */
6623 - setMiniwindowImage: (BOOL) setMini
6625 id image = [[self window] miniwindowImage];
6626 NSTRACE (setMiniwindowImage);
6628 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
6629 about "AppleDockIconEnabled" notwithstanding, however the set message
6630 below has its effect nonetheless. */
6631 if (image != emacsframe->output_data.ns->miniimage)
6633 if (image && [image isKindOfClass: [EmacsImage class]])
6635 [[self window] setMiniwindowImage:
6636 setMini ? emacsframe->output_data.ns->miniimage : nil];
6643 - (void) setRows: (int) r andColumns: (int) c
6649 @end /* EmacsView */
6653 /* ==========================================================================
6655 EmacsWindow implementation
6657 ========================================================================== */
6659 @implementation EmacsWindow
6661 #ifdef NS_IMPL_COCOA
6662 - (id)accessibilityAttributeValue:(NSString *)attribute
6664 Lisp_Object str = Qnil;
6665 struct frame *f = SELECTED_FRAME ();
6666 struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contents);
6668 if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
6669 return NSAccessibilityTextFieldRole;
6671 if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]
6672 && curbuf && ! NILP (BVAR (curbuf, mark_active)))
6674 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
6676 else if (curbuf && [attribute isEqualToString:NSAccessibilityValueAttribute])
6678 if (! NILP (BVAR (curbuf, mark_active)))
6679 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
6683 ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf);
6684 ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte;
6685 ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf);
6687 if (! NILP (BVAR (curbuf, enable_multibyte_characters)))
6688 str = make_uninit_multibyte_string (range, byte_range);
6690 str = make_uninit_string (range);
6691 /* To check: This returns emacs-utf-8, which is a superset of utf-8.
6692 Is this a problem? */
6693 memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range);
6700 if (CONSP (str) && SYMBOLP (XCAR (str)))
6703 if (CONSP (str) && NILP (XCDR (str)))
6708 const char *utfStr = SSDATA (str);
6709 NSString *nsStr = [NSString stringWithUTF8String: utfStr];
6714 return [super accessibilityAttributeValue:attribute];
6716 #endif /* NS_IMPL_COCOA */
6718 /* If we have multiple monitors, one above the other, we don't want to
6719 restrict the height to just one monitor. So we override this. */
6720 - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
6722 /* When making the frame visible for the first time or if there is just
6723 one screen, we want to constrain. Other times not. */
6724 NSUInteger nr_screens = [[NSScreen screens] count];
6725 struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
6726 NSTRACE (constrainFrameRect);
6728 if (nr_screens == 1)
6730 NSRect r = [super constrainFrameRect:frameRect toScreen:screen];
6734 if (f->output_data.ns->dont_constrain
6735 || ns_menu_bar_should_be_hidden ())
6738 f->output_data.ns->dont_constrain = 1;
6739 return [super constrainFrameRect:frameRect toScreen:screen];
6742 @end /* EmacsWindow */
6745 @implementation EmacsFSWindow
6747 - (BOOL)canBecomeKeyWindow
6752 - (BOOL)canBecomeMainWindow
6759 /* ==========================================================================
6761 EmacsScroller implementation
6763 ========================================================================== */
6766 @implementation EmacsScroller
6768 /* for repeat button push */
6769 #define SCROLL_BAR_FIRST_DELAY 0.5
6770 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
6772 + (CGFloat) scrollerWidth
6774 /* TODO: if we want to allow variable widths, this is the place to do it,
6775 however neither GNUstep nor Cocoa support it very well */
6776 return [NSScroller scrollerWidth];
6780 - initFrame: (NSRect )r window: (Lisp_Object)nwin
6782 NSTRACE (EmacsScroller_initFrame);
6784 r.size.width = [EmacsScroller scrollerWidth];
6785 [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
6786 [self setContinuous: YES];
6787 [self setEnabled: YES];
6789 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
6790 locked against the top and bottom edges, and right edge on OS X, where
6791 scrollers are on right. */
6792 #ifdef NS_IMPL_GNUSTEP
6793 [self setAutoresizingMask: NSViewMaxXMargin | NSViewHeightSizable];
6795 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
6800 pixel_height = NSHeight (r);
6801 if (pixel_height == 0) pixel_height = 1;
6802 min_portion = 20 / pixel_height;
6804 frame = XFRAME (XWINDOW (win)->frame);
6805 if (FRAME_LIVE_P (frame))
6808 EmacsView *view = FRAME_NS_VIEW (frame);
6809 NSView *sview = [[view window] contentView];
6810 NSArray *subs = [sview subviews];
6812 /* disable optimization stopping redraw of other scrollbars */
6813 view->scrollbarsNeedingUpdate = 0;
6814 for (i =[subs count]-1; i >= 0; i--)
6815 if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]])
6816 view->scrollbarsNeedingUpdate++;
6817 [sview addSubview: self];
6820 /* [self setFrame: r]; */
6826 - (void)setFrame: (NSRect)newRect
6828 NSTRACE (EmacsScroller_setFrame);
6829 /* block_input (); */
6830 pixel_height = NSHeight (newRect);
6831 if (pixel_height == 0) pixel_height = 1;
6832 min_portion = 20 / pixel_height;
6833 [super setFrame: newRect];
6835 /* unblock_input (); */
6841 NSTRACE (EmacsScroller_dealloc);
6843 wset_vertical_scroll_bar (XWINDOW (win), Qnil);
6871 /* ensure other scrollbar updates after deletion */
6872 view = (EmacsView *)FRAME_NS_VIEW (frame);
6874 view->scrollbarsNeedingUpdate++;
6875 [self removeFromSuperview];
6883 - (void)resetCursorRects
6885 NSRect visible = [self visibleRect];
6886 NSTRACE (resetCursorRects);
6888 if (!NSIsEmptyRect (visible))
6889 [self addCursorRect: visible cursor: [NSCursor arrowCursor]];
6890 [[NSCursor arrowCursor] setOnMouseEntered: YES];
6894 - (int) checkSamePosition: (int) position portion: (int) portion
6897 return em_position ==position && em_portion ==portion && em_whole ==whole
6898 && portion != whole; /* needed for resize empty buf */
6902 - setPosition: (int)position portion: (int)portion whole: (int)whole
6904 NSTRACE (setPosition);
6906 em_position = position;
6907 em_portion = portion;
6910 if (portion >= whole)
6912 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
6913 [self setKnobProportion: 1.0];
6914 [self setDoubleValue: 1.0];
6916 [self setFloatValue: 0.0 knobProportion: 1.0];
6923 portion = max ((float)whole*min_portion/pixel_height, portion);
6924 pos = (float)position / (whole - portion);
6925 por = (CGFloat)portion/whole;
6926 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
6927 [self setKnobProportion: por];
6928 [self setDoubleValue: pos];
6930 [self setFloatValue: pos knobProportion: por];
6934 /* Events may come here even if the event loop is not running.
6935 If we don't enter the event loop, the scroll bar will not update.
6936 So send SIGIO to ourselves. */
6937 if (apploopnr == 0) raise (SIGIO);
6942 /* FIXME: unused at moment (see ns_mouse_position) at the moment because
6943 drag events will go directly to the EmacsScroller. Leaving in for now. */
6944 -(void)getMouseMotionPart: (int *)part window: (Lisp_Object *)window
6945 x: (Lisp_Object *)x y: ( Lisp_Object *)y
6947 *part = last_hit_part;
6949 XSETINT (*y, pixel_height);
6950 if ([self floatValue] > 0.999F)
6951 XSETINT (*x, pixel_height);
6953 XSETINT (*x, pixel_height * [self floatValue]);
6957 /* set up emacs_event */
6958 - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
6963 emacs_event->part = last_hit_part;
6964 emacs_event->code = 0;
6965 emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier;
6966 emacs_event->frame_or_window = win;
6967 emacs_event->timestamp = EV_TIMESTAMP (e);
6968 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
6969 emacs_event->arg = Qnil;
6970 XSETINT (emacs_event->x, loc * pixel_height);
6971 XSETINT (emacs_event->y, pixel_height-20);
6975 n_emacs_events_pending++;
6976 kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
6979 hold_event (emacs_event);
6980 EVENT_INIT (*emacs_event);
6981 ns_send_appdefined (-1);
6985 /* called manually thru timer to implement repeated button action w/hold-down */
6986 - repeatScroll: (NSTimer *)scrollEntry
6988 NSEvent *e = [[self window] currentEvent];
6989 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
6990 BOOL inKnob = [self testPart: p] == NSScrollerKnob;
6992 /* clear timer if need be */
6993 if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
6995 [scroll_repeat_entry invalidate];
6996 [scroll_repeat_entry release];
6997 scroll_repeat_entry = nil;
7003 = [[NSTimer scheduledTimerWithTimeInterval:
7004 SCROLL_BAR_CONTINUOUS_DELAY
7006 selector: @selector (repeatScroll:)
7012 [self sendScrollEventAtLoc: 0 fromEvent: e];
7017 /* Asynchronous mouse tracking for scroller. This allows us to dispatch
7018 mouseDragged events without going into a modal loop. */
7019 - (void)mouseDown: (NSEvent *)e
7022 /* hitPart is only updated AFTER event is passed on */
7023 NSScrollerPart part = [self testPart: [e locationInWindow]];
7024 CGFloat inc = 0.0, loc, kloc, pos;
7027 NSTRACE (EmacsScroller_mouseDown);
7031 case NSScrollerDecrementPage:
7032 last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
7033 case NSScrollerIncrementPage:
7034 last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
7035 case NSScrollerDecrementLine:
7036 last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
7037 case NSScrollerIncrementLine:
7038 last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
7039 case NSScrollerKnob:
7040 last_hit_part = scroll_bar_handle; break;
7041 case NSScrollerKnobSlot: /* GNUstep-only */
7042 last_hit_part = scroll_bar_move_ratio; break;
7043 default: /* NSScrollerNoPart? */
7044 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %ld\n",
7051 pos = 0; /* ignored */
7053 /* set a timer to repeat, as we can't let superclass do this modally */
7055 = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY
7057 selector: @selector (repeatScroll:)
7064 /* handle, or on GNUstep possibly slot */
7065 NSEvent *fake_event;
7067 /* compute float loc in slot and mouse offset on knob */
7068 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
7070 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
7076 else if (loc >= NSHeight (sr))
7078 loc = NSHeight (sr);
7086 kr = [self convertRect: [self rectForPart: NSScrollerKnob]
7088 kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
7090 last_mouse_offset = kloc;
7092 /* if knob, tell emacs a location offset by knob pos
7093 (to indicate top of handle) */
7094 if (part == NSScrollerKnob)
7095 pos = (loc - last_mouse_offset) / NSHeight (sr);
7097 /* else this is a slot click on GNUstep: go straight there */
7098 pos = loc / NSHeight (sr);
7100 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
7101 fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
7102 location: [e locationInWindow]
7103 modifierFlags: [e modifierFlags]
7104 timestamp: [e timestamp]
7105 windowNumber: [e windowNumber]
7106 context: [e context]
7107 eventNumber: [e eventNumber]
7108 clickCount: [e clickCount]
7109 pressure: [e pressure]];
7110 [super mouseUp: fake_event];
7113 if (part != NSScrollerKnob)
7114 [self sendScrollEventAtLoc: pos fromEvent: e];
7118 /* Called as we manually track scroller drags, rather than superclass. */
7119 - (void)mouseDragged: (NSEvent *)e
7124 NSTRACE (EmacsScroller_mouseDragged);
7126 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
7128 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
7134 else if (loc >= NSHeight (sr) + last_mouse_offset)
7136 loc = NSHeight (sr) + last_mouse_offset;
7139 pos = (loc - last_mouse_offset) / NSHeight (sr);
7140 [self sendScrollEventAtLoc: pos fromEvent: e];
7144 - (void)mouseUp: (NSEvent *)e
7146 if (scroll_repeat_entry)
7148 [scroll_repeat_entry invalidate];
7149 [scroll_repeat_entry release];
7150 scroll_repeat_entry = nil;
7156 /* treat scrollwheel events in the bar as though they were in the main window */
7157 - (void) scrollWheel: (NSEvent *)theEvent
7159 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
7160 [view mouseDown: theEvent];
7163 @end /* EmacsScroller */
7166 #ifdef NS_IMPL_GNUSTEP
7167 /* Dummy class to get rid of startup warnings. */
7168 @implementation EmacsDocument
7174 /* ==========================================================================
7176 Font-related functions; these used to be in nsfaces.m
7178 ========================================================================== */
7182 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7184 struct font *font = XFONT_OBJECT (font_object);
7187 fontset = fontset_from_font (font_object);
7188 FRAME_FONTSET (f) = fontset;
7190 if (FRAME_FONT (f) == font)
7191 /* This font is already set in frame F. There's nothing more to
7195 FRAME_FONT (f) = font;
7197 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
7198 FRAME_COLUMN_WIDTH (f) = font->average_width;
7199 FRAME_LINE_HEIGHT (f) = font->height;
7201 compute_fringe_widths (f, 1);
7203 /* Compute the scroll bar width in character columns. */
7204 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
7206 int wid = FRAME_COLUMN_WIDTH (f);
7207 FRAME_CONFIG_SCROLL_BAR_COLS (f)
7208 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
7212 int wid = FRAME_COLUMN_WIDTH (f);
7213 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
7216 /* Now make the frame display the given font. */
7217 if (FRAME_NS_WINDOW (f) != 0)
7218 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
7224 /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
7225 /* Note: ns_font_to_xlfd and ns_fontname_to_xlfd no longer needed, removed
7229 ns_xlfd_to_fontname (const char *xlfd)
7230 /* --------------------------------------------------------------------------
7231 Convert an X font name (XLFD) to an NS font name.
7232 Only family is used.
7233 The string returned is temporarily allocated.
7234 -------------------------------------------------------------------------- */
7236 char *name = xmalloc (180);
7240 if (!strncmp (xlfd, "--", 2))
7241 sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
7243 sscanf (xlfd, "-%*[^-]-%[^-]179-", name);
7245 /* stopgap for malformed XLFD input */
7246 if (strlen (name) == 0)
7247 strcpy (name, "Monaco");
7249 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
7250 also uppercase after '-' or ' ' */
7251 name[0] = c_toupper (name[0]);
7252 for (len =strlen (name), i =0; i<len; i++)
7258 name[i+1] = c_toupper (name[i+1]);
7260 else if (name[i] == '_')
7264 name[i+1] = c_toupper (name[i+1]);
7267 /*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
7268 ret = [[NSString stringWithUTF8String: name] UTF8String];
7275 syms_of_nsterm (void)
7277 NSTRACE (syms_of_nsterm);
7279 ns_antialias_threshold = 10.0;
7281 /* from 23+ we need to tell emacs what modifiers there are.. */
7282 DEFSYM (Qmodifier_value, "modifier-value");
7283 DEFSYM (Qalt, "alt");
7284 DEFSYM (Qhyper, "hyper");
7285 DEFSYM (Qmeta, "meta");
7286 DEFSYM (Qsuper, "super");
7287 DEFSYM (Qcontrol, "control");
7288 DEFSYM (QUTF8_STRING, "UTF8_STRING");
7290 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
7291 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
7292 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
7293 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
7294 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
7296 DEFVAR_LISP ("ns-input-file", ns_input_file,
7297 "The file specified in the last NS event.");
7298 ns_input_file =Qnil;
7300 DEFVAR_LISP ("ns-input-text", ns_input_text,
7301 "The data received in the last NS text drag event.");
7302 ns_input_text =Qnil;
7304 DEFVAR_LISP ("ns-working-text", ns_working_text,
7305 "String for visualizing working composition sequence.");
7306 ns_working_text =Qnil;
7308 DEFVAR_LISP ("ns-input-font", ns_input_font,
7309 "The font specified in the last NS event.");
7310 ns_input_font =Qnil;
7312 DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize,
7313 "The fontsize specified in the last NS event.");
7314 ns_input_fontsize =Qnil;
7316 DEFVAR_LISP ("ns-input-line", ns_input_line,
7317 "The line specified in the last NS event.");
7318 ns_input_line =Qnil;
7320 DEFVAR_LISP ("ns-input-color", ns_input_color,
7321 "The color specified in the last NS event.");
7322 ns_input_color =Qnil;
7324 DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
7325 "The service name specified in the last NS event.");
7326 ns_input_spi_name =Qnil;
7328 DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg,
7329 "The service argument specified in the last NS event.");
7330 ns_input_spi_arg =Qnil;
7332 DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier,
7333 "This variable describes the behavior of the alternate or option key.\n\
7334 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7335 Set to none means that the alternate / option key is not interpreted by Emacs\n\
7336 at all, allowing it to be used at a lower level for accented character entry.");
7337 ns_alternate_modifier = Qmeta;
7339 DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier,
7340 "This variable describes the behavior of the right alternate or option key.\n\
7341 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7342 Set to left means be the same key as `ns-alternate-modifier'.\n\
7343 Set to none means that the alternate / option key is not interpreted by Emacs\n\
7344 at all, allowing it to be used at a lower level for accented character entry.");
7345 ns_right_alternate_modifier = Qleft;
7347 DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
7348 "This variable describes the behavior of the command key.\n\
7349 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
7350 ns_command_modifier = Qsuper;
7352 DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
7353 "This variable describes the behavior of the right command key.\n\
7354 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7355 Set to left means be the same key as `ns-command-modifier'.\n\
7356 Set to none means that the command / option key is not interpreted by Emacs\n\
7357 at all, allowing it to be used at a lower level for accented character entry.");
7358 ns_right_command_modifier = Qleft;
7360 DEFVAR_LISP ("ns-control-modifier", ns_control_modifier,
7361 "This variable describes the behavior of the control key.\n\
7362 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
7363 ns_control_modifier = Qcontrol;
7365 DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier,
7366 "This variable describes the behavior of the right control key.\n\
7367 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7368 Set to left means be the same key as `ns-control-modifier'.\n\
7369 Set to none means that the control / option key is not interpreted by Emacs\n\
7370 at all, allowing it to be used at a lower level for accented character entry.");
7371 ns_right_control_modifier = Qleft;
7373 DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
7374 "This variable describes the behavior of the function key (on laptops).\n\
7375 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
7376 Set to none means that the function key is not interpreted by Emacs at all,\n\
7377 allowing it to be used at a lower level for accented character entry.");
7378 ns_function_modifier = Qnone;
7380 DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
7381 "Non-nil (the default) means to render text antialiased.");
7382 ns_antialias_text = Qt;
7384 DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
7385 "Whether to confirm application quit using dialog.");
7386 ns_confirm_quit = Qnil;
7388 staticpro (&ns_display_name_list);
7389 ns_display_name_list = Qnil;
7391 staticpro (&last_mouse_motion_frame);
7392 last_mouse_motion_frame = Qnil;
7394 DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
7395 doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
7396 Only works on OSX 10.6 or later. */);
7397 ns_auto_hide_menu_bar = Qnil;
7399 DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen,
7400 doc: /*Non-nil means to use native fullscreen on OSX >= 10.7.
7401 Nil means use fullscreen the old (< 10.7) way. The old way works better with
7402 multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7.
7403 Default is t for OSX >= 10.7, nil otherwise. */);
7404 #ifdef HAVE_NATIVE_FS
7405 ns_use_native_fullscreen = YES;
7407 ns_use_native_fullscreen = NO;
7409 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
7411 /* TODO: move to common code */
7412 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
7413 doc: /* Which toolkit scroll bars Emacs uses, if any.
7414 A value of nil means Emacs doesn't use toolkit scroll bars.
7415 With the X Window system, the value is a symbol describing the
7416 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
7417 With MS Windows or Nextstep, the value is t. */);
7418 Vx_toolkit_scroll_bars = Qt;
7420 DEFVAR_BOOL ("x-use-underline-position-properties",
7421 x_use_underline_position_properties,
7422 doc: /*Non-nil means make use of UNDERLINE_POSITION font properties.
7423 A value of nil means ignore them. If you encounter fonts with bogus
7424 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
7425 to 4.1, set this to nil. */);
7426 x_use_underline_position_properties = 0;
7428 DEFVAR_BOOL ("x-underline-at-descent-line",
7429 x_underline_at_descent_line,
7430 doc: /* Non-nil means to draw the underline at the same place as the descent line.
7431 A value of nil means to draw the underline according to the value of the
7432 variable `x-use-underline-position-properties', which is usually at the
7433 baseline level. The default value is nil. */);
7434 x_underline_at_descent_line = 0;
7436 /* Tell Emacs about this window system. */
7437 Fprovide (Qns, Qnil);