1 /* NeXT/Open/GNUstep / MacOSX communication module. -*- coding: utf-8 -*-
3 Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2015 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
72 extern NSString *NSMenuDidBeginTrackingNotification;
75 /* ==========================================================================
77 NSTRACE, Trace support.
79 ========================================================================== */
83 /* The following use "volatile" since they can be accessed from
85 volatile int nstrace_num = 0;
86 volatile int nstrace_depth = 0;
88 /* When 0, no trace is emitted. This is used by NSTRACE_WHEN and
89 NSTRACE_UNLESS to silence functions called.
91 TODO: This should really be a thread-local variable, to avoid that
92 a function with disabled trace thread silence trace output in
93 another. However, in practice this seldom is a problem. */
94 volatile int nstrace_enabled_global = 1;
96 /* Called when nstrace_enabled goes out of scope. */
97 void nstrace_leave(int * pointer_to_nstrace_enabled)
99 if (*pointer_to_nstrace_enabled)
106 /* Called when nstrace_saved_enabled_global goes out of scope. */
107 void nstrace_restore_global_trace_state(int * pointer_to_saved_enabled_global)
109 nstrace_enabled_global = *pointer_to_saved_enabled_global;
113 char const * nstrace_fullscreen_type_name (int fs_type)
117 case -1: return "-1";
118 case FULLSCREEN_NONE: return "FULLSCREEN_NONE";
119 case FULLSCREEN_WIDTH: return "FULLSCREEN_WIDTH";
120 case FULLSCREEN_HEIGHT: return "FULLSCREEN_HEIGHT";
121 case FULLSCREEN_BOTH: return "FULLSCREEN_BOTH";
122 case FULLSCREEN_MAXIMIZED: return "FULLSCREEN_MAXIMIZED";
123 default: return "FULLSCREEN_?????";
129 /* ==========================================================================
131 NSColor, EmacsColor category.
133 ========================================================================== */
134 @implementation NSColor (EmacsColor)
135 + (NSColor *)colorForEmacsRed:(CGFloat)red green:(CGFloat)green
136 blue:(CGFloat)blue alpha:(CGFloat)alpha
139 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
140 if (ns_use_srgb_colorspace)
141 return [NSColor colorWithSRGBRed: red
147 return [NSColor colorWithCalibratedRed: red
153 - (NSColor *)colorUsingDefaultColorSpace
156 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
157 if (ns_use_srgb_colorspace)
158 return [self colorUsingColorSpace: [NSColorSpace sRGBColorSpace]];
161 return [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
166 /* ==========================================================================
170 ========================================================================== */
172 /* Convert a symbol indexed with an NSxxx value to a value as defined
173 in keyboard.c (lispy_function_key). I hope this is a correct way
174 of doing things... */
175 static unsigned convert_ns_to_X_keysym[] =
177 NSHomeFunctionKey, 0x50,
178 NSLeftArrowFunctionKey, 0x51,
179 NSUpArrowFunctionKey, 0x52,
180 NSRightArrowFunctionKey, 0x53,
181 NSDownArrowFunctionKey, 0x54,
182 NSPageUpFunctionKey, 0x55,
183 NSPageDownFunctionKey, 0x56,
184 NSEndFunctionKey, 0x57,
185 NSBeginFunctionKey, 0x58,
186 NSSelectFunctionKey, 0x60,
187 NSPrintFunctionKey, 0x61,
188 NSClearLineFunctionKey, 0x0B,
189 NSExecuteFunctionKey, 0x62,
190 NSInsertFunctionKey, 0x63,
191 NSUndoFunctionKey, 0x65,
192 NSRedoFunctionKey, 0x66,
193 NSMenuFunctionKey, 0x67,
194 NSFindFunctionKey, 0x68,
195 NSHelpFunctionKey, 0x6A,
196 NSBreakFunctionKey, 0x6B,
198 NSF1FunctionKey, 0xBE,
199 NSF2FunctionKey, 0xBF,
200 NSF3FunctionKey, 0xC0,
201 NSF4FunctionKey, 0xC1,
202 NSF5FunctionKey, 0xC2,
203 NSF6FunctionKey, 0xC3,
204 NSF7FunctionKey, 0xC4,
205 NSF8FunctionKey, 0xC5,
206 NSF9FunctionKey, 0xC6,
207 NSF10FunctionKey, 0xC7,
208 NSF11FunctionKey, 0xC8,
209 NSF12FunctionKey, 0xC9,
210 NSF13FunctionKey, 0xCA,
211 NSF14FunctionKey, 0xCB,
212 NSF15FunctionKey, 0xCC,
213 NSF16FunctionKey, 0xCD,
214 NSF17FunctionKey, 0xCE,
215 NSF18FunctionKey, 0xCF,
216 NSF19FunctionKey, 0xD0,
217 NSF20FunctionKey, 0xD1,
218 NSF21FunctionKey, 0xD2,
219 NSF22FunctionKey, 0xD3,
220 NSF23FunctionKey, 0xD4,
221 NSF24FunctionKey, 0xD5,
223 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
224 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
225 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
227 NSTabCharacter, 0x09,
228 0x19, 0x09, /* left tab->regular since pass shift */
229 NSCarriageReturnCharacter, 0x0D,
230 NSNewlineCharacter, 0x0D,
231 NSEnterCharacter, 0x8D,
233 0x41|NSNumericPadKeyMask, 0xAE, /* KP_Decimal */
234 0x43|NSNumericPadKeyMask, 0xAA, /* KP_Multiply */
235 0x45|NSNumericPadKeyMask, 0xAB, /* KP_Add */
236 0x4B|NSNumericPadKeyMask, 0xAF, /* KP_Divide */
237 0x4E|NSNumericPadKeyMask, 0xAD, /* KP_Subtract */
238 0x51|NSNumericPadKeyMask, 0xBD, /* KP_Equal */
239 0x52|NSNumericPadKeyMask, 0xB0, /* KP_0 */
240 0x53|NSNumericPadKeyMask, 0xB1, /* KP_1 */
241 0x54|NSNumericPadKeyMask, 0xB2, /* KP_2 */
242 0x55|NSNumericPadKeyMask, 0xB3, /* KP_3 */
243 0x56|NSNumericPadKeyMask, 0xB4, /* KP_4 */
244 0x57|NSNumericPadKeyMask, 0xB5, /* KP_5 */
245 0x58|NSNumericPadKeyMask, 0xB6, /* KP_6 */
246 0x59|NSNumericPadKeyMask, 0xB7, /* KP_7 */
247 0x5B|NSNumericPadKeyMask, 0xB8, /* KP_8 */
248 0x5C|NSNumericPadKeyMask, 0xB9, /* KP_9 */
250 0x1B, 0x1B /* escape */
253 /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
254 the maximum font size to NOT antialias. On GNUstep there is currently
255 no way to control this behavior. */
256 float ns_antialias_threshold;
258 NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
259 NSString *ns_app_name = @"Emacs"; /* default changed later */
261 /* Display variables */
262 struct ns_display_info *x_display_list; /* Chain of existing displays */
263 long context_menu_value = 0;
266 static struct frame *ns_updating_frame;
267 static NSView *focus_view = NULL;
268 static int ns_window_num = 0;
269 #ifdef NS_IMPL_GNUSTEP
270 static NSRect uRect; // TODO: This is dead, remove it?
272 static BOOL gsaved = NO;
273 static BOOL ns_fake_keydown = NO;
275 static BOOL ns_menu_bar_is_hidden = NO;
277 /*static int debug_lock = 0; */
280 static BOOL send_appdefined = YES;
281 #define NO_APPDEFINED_DATA (-8)
282 static int last_appdefined_event_data = NO_APPDEFINED_DATA;
283 static NSTimer *timed_entry = 0;
284 static NSTimer *scroll_repeat_entry = nil;
285 static fd_set select_readfds, select_writefds;
286 enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 };
287 static int select_nfds = 0, select_valid = 0;
288 static struct timespec select_timeout = { 0, 0 };
289 static int selfds[2] = { -1, -1 };
290 static pthread_mutex_t select_mutex;
291 static int apploopnr = 0;
292 static NSAutoreleasePool *outerpool;
293 static struct input_event *emacs_event = NULL;
294 static struct input_event *q_event_ptr = NULL;
295 static int n_emacs_events_pending = 0;
296 static NSMutableArray *ns_pending_files, *ns_pending_service_names,
297 *ns_pending_service_args;
298 static BOOL ns_do_open_file = NO;
299 static BOOL ns_last_use_native_fullscreen;
301 /* Non-zero means that a HELP_EVENT has been generated since Emacs
304 static BOOL any_help_event_p = NO;
307 struct input_event *q;
313 static NSString *represented_filename = nil;
314 static struct frame *represented_frame = 0;
318 * State for pending menu activation:
319 * MENU_NONE Normal state
320 * MENU_PENDING A menu has been clicked on, but has been canceled so we can
321 * run lisp to update the menu.
322 * MENU_OPENING Menu is up to date, and the click event is redone so the menu
326 #define MENU_PENDING 1
327 #define MENU_OPENING 2
328 static int menu_will_open_state = MENU_NONE;
330 /* Saved position for menu click. */
331 static CGPoint menu_mouse_point;
334 /* Convert modifiers in a NeXTstep event to emacs style modifiers. */
335 #define NS_FUNCTION_KEY_MASK 0x800000
336 #define NSLeftControlKeyMask (0x000001 | NSControlKeyMask)
337 #define NSRightControlKeyMask (0x002000 | NSControlKeyMask)
338 #define NSLeftCommandKeyMask (0x000008 | NSCommandKeyMask)
339 #define NSRightCommandKeyMask (0x000010 | NSCommandKeyMask)
340 #define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
341 #define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
342 #define EV_MODIFIERS2(flags) \
343 (((flags & NSHelpKeyMask) ? \
344 hyper_modifier : 0) \
345 | (!EQ (ns_right_alternate_modifier, Qleft) && \
346 ((flags & NSRightAlternateKeyMask) \
347 == NSRightAlternateKeyMask) ? \
348 parse_solitary_modifier (ns_right_alternate_modifier) : 0) \
349 | ((flags & NSAlternateKeyMask) ? \
350 parse_solitary_modifier (ns_alternate_modifier) : 0) \
351 | ((flags & NSShiftKeyMask) ? \
352 shift_modifier : 0) \
353 | (!EQ (ns_right_control_modifier, Qleft) && \
354 ((flags & NSRightControlKeyMask) \
355 == NSRightControlKeyMask) ? \
356 parse_solitary_modifier (ns_right_control_modifier) : 0) \
357 | ((flags & NSControlKeyMask) ? \
358 parse_solitary_modifier (ns_control_modifier) : 0) \
359 | ((flags & NS_FUNCTION_KEY_MASK) ? \
360 parse_solitary_modifier (ns_function_modifier) : 0) \
361 | (!EQ (ns_right_command_modifier, Qleft) && \
362 ((flags & NSRightCommandKeyMask) \
363 == NSRightCommandKeyMask) ? \
364 parse_solitary_modifier (ns_right_command_modifier) : 0) \
365 | ((flags & NSCommandKeyMask) ? \
366 parse_solitary_modifier (ns_command_modifier):0))
367 #define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags])
369 #define EV_UDMODIFIERS(e) \
370 ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
371 | (([e type] == NSRightMouseDown) ? down_modifier : 0) \
372 | (([e type] == NSOtherMouseDown) ? down_modifier : 0) \
373 | (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
374 | (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
375 | (([e type] == NSOtherMouseDragged) ? down_modifier : 0) \
376 | (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
377 | (([e type] == NSRightMouseUp) ? up_modifier : 0) \
378 | (([e type] == NSOtherMouseUp) ? up_modifier : 0))
380 #define EV_BUTTON(e) \
381 ((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
382 (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : \
383 [e buttonNumber] - 1)
385 /* Convert the time field to a timestamp in milliseconds. */
386 #define EV_TIMESTAMP(e) ([e timestamp] * 1000)
388 /* This is a piece of code which is common to all the event handling
389 methods. Maybe it should even be a function. */
390 #define EV_TRAILER(e) \
392 XSETFRAME (emacs_event->frame_or_window, emacsframe); \
396 #define EV_TRAILER2(e) \
398 if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
401 Lisp_Object tem = Vinhibit_quit; \
402 Vinhibit_quit = Qt; \
403 n_emacs_events_pending++; \
404 kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
405 Vinhibit_quit = tem; \
408 hold_event (emacs_event); \
409 EVENT_INIT (*emacs_event); \
410 ns_send_appdefined (-1); \
413 /* TODO: get rid of need for these forward declarations */
414 static void ns_condemn_scroll_bars (struct frame *f);
415 static void ns_judge_scroll_bars (struct frame *f);
416 void x_set_frame_alpha (struct frame *f);
419 /* ==========================================================================
423 ========================================================================== */
426 ns_set_represented_filename (NSString* fstr, struct frame *f)
428 represented_filename = [fstr retain];
429 represented_frame = f;
433 ns_init_events (struct input_event* ev)
446 hold_event (struct input_event *event)
448 if (hold_event_q.nr == hold_event_q.cap)
450 if (hold_event_q.cap == 0) hold_event_q.cap = 10;
451 else hold_event_q.cap *= 2;
453 xrealloc (hold_event_q.q, hold_event_q.cap * sizeof *hold_event_q.q);
456 hold_event_q.q[hold_event_q.nr++] = *event;
457 /* Make sure ns_read_socket is called, i.e. we have input. */
459 send_appdefined = YES;
463 append2 (Lisp_Object list, Lisp_Object item)
464 /* --------------------------------------------------------------------------
465 Utility to append to a list
466 -------------------------------------------------------------------------- */
468 return CALLN (Fnconc, list, list1 (item));
473 ns_etc_directory (void)
474 /* If running as a self-contained app bundle, return as a string the
475 filename of the etc directory, if present; else nil. */
477 NSBundle *bundle = [NSBundle mainBundle];
478 NSString *resourceDir = [bundle resourcePath];
479 NSString *resourcePath;
480 NSFileManager *fileManager = [NSFileManager defaultManager];
483 resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"];
484 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
486 if (isDir) return [resourcePath UTF8String];
494 /* If running as a self-contained app bundle, return as a path string
495 the filenames of the libexec and bin directories, ie libexec:bin.
496 Otherwise, return nil.
497 Normally, Emacs does not add its own bin/ directory to the PATH.
498 However, a self-contained NS build has a different layout, with
499 bin/ and libexec/ subdirectories in the directory that contains
501 We put libexec first, because init_callproc_1 uses the first
502 element to initialize exec-directory. An alternative would be
503 for init_callproc to check for invocation-directory/libexec.
506 NSBundle *bundle = [NSBundle mainBundle];
507 NSString *resourceDir = [bundle resourcePath];
508 NSString *binDir = [bundle bundlePath];
509 NSString *resourcePath, *resourcePaths;
511 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
512 NSFileManager *fileManager = [NSFileManager defaultManager];
514 NSEnumerator *pathEnum;
517 range = [resourceDir rangeOfString: @"Contents"];
518 if (range.location != NSNotFound)
520 binDir = [binDir stringByAppendingPathComponent: @"Contents"];
522 binDir = [binDir stringByAppendingPathComponent: @"MacOS"];
526 paths = [binDir stringsByAppendingPaths:
527 [NSArray arrayWithObjects: @"libexec", @"bin", nil]];
528 pathEnum = [paths objectEnumerator];
531 while ((resourcePath = [pathEnum nextObject]))
533 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
536 if ([resourcePaths length] > 0)
538 = [resourcePaths stringByAppendingString: pathSeparator];
540 = [resourcePaths stringByAppendingString: resourcePath];
543 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
551 /* If running as a self-contained app bundle, return as a path string
552 the filenames of the site-lisp and lisp directories.
553 Ie, site-lisp:lisp. Otherwise, return nil. */
555 NSBundle *bundle = [NSBundle mainBundle];
556 NSString *resourceDir = [bundle resourcePath];
557 NSString *resourcePath, *resourcePaths;
558 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
559 NSFileManager *fileManager = [NSFileManager defaultManager];
561 NSArray *paths = [resourceDir stringsByAppendingPaths:
562 [NSArray arrayWithObjects:
563 @"site-lisp", @"lisp", nil]];
564 NSEnumerator *pathEnum = [paths objectEnumerator];
567 /* Hack to skip site-lisp. */
568 if (no_site_lisp) resourcePath = [pathEnum nextObject];
570 while ((resourcePath = [pathEnum nextObject]))
572 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
575 if ([resourcePaths length] > 0)
577 = [resourcePaths stringByAppendingString: pathSeparator];
579 = [resourcePaths stringByAppendingString: resourcePath];
582 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
589 ns_release_object (void *obj)
590 /* --------------------------------------------------------------------------
591 Release an object (callable from C)
592 -------------------------------------------------------------------------- */
599 ns_retain_object (void *obj)
600 /* --------------------------------------------------------------------------
601 Retain an object (callable from C)
602 -------------------------------------------------------------------------- */
609 ns_alloc_autorelease_pool (void)
610 /* --------------------------------------------------------------------------
611 Allocate a pool for temporary objects (callable from C)
612 -------------------------------------------------------------------------- */
614 return [[NSAutoreleasePool alloc] init];
619 ns_release_autorelease_pool (void *pool)
620 /* --------------------------------------------------------------------------
621 Free a pool and temporary objects it refers to (callable from C)
622 -------------------------------------------------------------------------- */
624 ns_release_object (pool);
628 /* True, if the menu bar should be hidden. */
631 ns_menu_bar_should_be_hidden (void)
633 return !NILP (ns_auto_hide_menu_bar)
634 && [NSApp respondsToSelector:@selector(setPresentationOptions:)];
639 ns_menu_bar_height (NSScreen *screen)
640 /* The height of the menu bar, if visible. */
642 // NSTRACE ("ns_menu_bar_height");
646 if (ns_menu_bar_should_be_hidden())
652 NSRect screenFrame = [screen frame];
653 NSRect screenVisibleFrame = [screen visibleFrame];
655 CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height;
656 CGFloat visibleFrameTop = (screenVisibleFrame.origin.y
657 + screenVisibleFrame.size.height);
659 res = frameTop - visibleFrameTop;
663 // NSTRACE_MSG (NSTRACE_FMT_RETURN "%.0f", res);
669 /* ==========================================================================
671 Focus (clipping) and screen update
673 ========================================================================== */
676 // Window constraining
677 // -------------------
679 // To ensure that the windows are not placed under the menu bar, they
680 // are typically moved by the call-back constrainFrameRect. However,
681 // by overriding it, it's possible to inhibit this, leaving the window
682 // in it's original position.
684 // It's possible to hide the menu bar. However, technically, it's only
685 // possible to hide it when the application is active. To ensure that
686 // this work properly, the menu bar and window constraining are
687 // deferred until the application becomes active.
689 // Even though it's not possible to manually move a window above the
690 // top of the screen, it is allowed if it's done programmatically,
691 // when the menu is hidden. This allows the editable area to cover the
692 // full screen height.
697 // Use the following extra files:
700 // ;; Hide menu and place frame slightly above the top of the screen.
701 // (setq ns-auto-hide-menu-bar t)
702 // (set-frame-position (selected-frame) 0 -20)
706 // emacs -Q -l init.el
708 // Result: No menu bar, and the title bar should be above the screen.
714 // Result: Menu bar visible, frame placed immediately below the menu.
717 static NSRect constrain_frame_rect(NSRect frameRect)
719 NSTRACE ("constrain_frame_rect(" NSTRACE_FMT_RECT ")",
720 NSTRACE_ARG_RECT (frameRect));
722 // --------------------
723 // Collect information about the screen the frame is covering.
726 NSArray *screens = [NSScreen screens];
727 NSUInteger nr_screens = [screens count];
731 // The height of the menu bar, if present in any screen the frame is
733 int menu_bar_height = 0;
735 // A rectangle covering all the screen the frame is displayed in.
736 NSRect multiscreenRect = NSMakeRect(0, 0, 0, 0);
737 for (i = 0; i < nr_screens; ++i )
739 NSScreen *s = [screens objectAtIndex: i];
740 NSRect scrRect = [s frame];
742 NSTRACE_MSG ("Screen %d: " NSTRACE_FMT_RECT,
743 i, NSTRACE_ARG_RECT (scrRect));
745 if (NSIntersectionRect (frameRect, scrRect).size.height != 0)
747 multiscreenRect = NSUnionRect (multiscreenRect, scrRect);
749 menu_bar_height = max(menu_bar_height, ns_menu_bar_height (s));
753 NSTRACE_RECT ("multiscreenRect", multiscreenRect);
755 NSTRACE_MSG ("menu_bar_height: %d", menu_bar_height);
757 if (multiscreenRect.size.width == 0
758 || multiscreenRect.size.height == 0)
760 // Failed to find any monitor, give up.
761 NSTRACE_MSG ("multiscreenRect empty");
762 NSTRACE_RETURN_RECT (frameRect);
767 // --------------------
768 // Find a suitable placement.
771 if (ns_menu_bar_should_be_hidden())
773 // When the menu bar is hidden, the user may place part of the
774 // frame above the top of the screen, for example to hide the
777 // Hence, keep the original position.
781 // Ensure that the frame is below the menu bar, or below the top
784 // This assume that the menu bar is placed at the top in the
785 // rectangle that covers the monitors. (It doesn't have to be,
786 // but if it's not it's hard to do anything useful.)
787 CGFloat topOfWorkArea = (multiscreenRect.origin.y
788 + multiscreenRect.size.height
791 CGFloat topOfFrame = frameRect.origin.y + frameRect.size.height;
792 if (topOfFrame > topOfWorkArea)
794 frameRect.origin.y -= topOfFrame - topOfWorkArea;
795 NSTRACE_RECT ("After placement adjust", frameRect);
799 // Include the following section to restrict frame to the screens.
800 // (If so, update it to allow the frame to stretch down below the
803 // --------------------
804 // Ensure frame doesn't stretch below the screens.
807 CGFloat diff = multiscreenRect.origin.y - frameRect.origin.y;
811 frameRect.origin.y = multiscreenRect.origin.y;
812 frameRect.size.height -= diff;
816 NSTRACE_RETURN_RECT (frameRect);
822 ns_constrain_all_frames (void)
823 /* --------------------------------------------------------------------------
824 Ensure that the menu bar doesn't cover any frames.
825 -------------------------------------------------------------------------- */
827 Lisp_Object tail, frame;
829 NSTRACE ("ns_constrain_all_frames");
833 FOR_EACH_FRAME (tail, frame)
835 struct frame *f = XFRAME (frame);
838 EmacsView *view = FRAME_NS_VIEW (f);
840 if (![view isFullscreen])
843 setFrame:constrain_frame_rect([[view window] frame])
854 ns_update_auto_hide_menu_bar (void)
855 /* --------------------------------------------------------------------------
856 Show or hide the menu bar, based on user setting.
857 -------------------------------------------------------------------------- */
860 NSTRACE ("ns_update_auto_hide_menu_bar");
864 if (NSApp != nil && [NSApp isActive])
866 // Note, "setPresentationOptions" triggers an error unless the
867 // application is active.
868 BOOL menu_bar_should_be_hidden = ns_menu_bar_should_be_hidden ();
870 if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden)
872 NSApplicationPresentationOptions options
873 = NSApplicationPresentationDefault;
875 if (menu_bar_should_be_hidden)
876 options |= NSApplicationPresentationAutoHideMenuBar
877 | NSApplicationPresentationAutoHideDock;
879 [NSApp setPresentationOptions: options];
881 ns_menu_bar_is_hidden = menu_bar_should_be_hidden;
883 if (!ns_menu_bar_is_hidden)
885 ns_constrain_all_frames ();
896 ns_update_begin (struct frame *f)
897 /* --------------------------------------------------------------------------
898 Prepare for a grouped sequence of drawing calls
899 external (RIF) call; whole frame, called before update_window_begin
900 -------------------------------------------------------------------------- */
902 EmacsView *view = FRAME_NS_VIEW (f);
903 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_begin");
905 ns_update_auto_hide_menu_bar ();
908 if ([view isFullscreen] && [view fsIsNative])
910 // Fix reappearing tool bar in fullscreen for OSX 10.7
911 BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (f) ? YES : NO;
912 NSToolbar *toolbar = [FRAME_NS_VIEW (f) toolbar];
913 if (! tbar_visible != ! [toolbar isVisible])
914 [toolbar setVisible: tbar_visible];
918 ns_updating_frame = f;
921 /* drawRect may have been called for say the minibuffer, and then clip path
922 is for the minibuffer. But the display engine may draw more because
923 we have set the frame as garbaged. So reset clip path to the whole
928 NSRect r = [view frame];
929 NSRect cr = [[view window] frame];
930 /* If a large frame size is set, r may be larger than the window frame
931 before constrained. In that case don't change the clip path, as we
932 will clear in to the tool bar and title bar. */
934 + FRAME_NS_TITLEBAR_HEIGHT (f)
935 + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height)
937 bp = [[NSBezierPath bezierPathWithRect: r] retain];
944 #ifdef NS_IMPL_GNUSTEP
945 uRect = NSMakeRect (0, 0, 0, 0);
951 ns_update_window_begin (struct window *w)
952 /* --------------------------------------------------------------------------
953 Prepare for a grouped sequence of drawing calls
954 external (RIF) call; for one window, called after update_begin
955 -------------------------------------------------------------------------- */
957 struct frame *f = XFRAME (WINDOW_FRAME (w));
958 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
960 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_begin");
961 w->output_cursor = w->cursor;
965 if (f == hlinfo->mouse_face_mouse_frame)
967 /* Don't do highlighting for mouse motion during the update. */
968 hlinfo->mouse_face_defer = 1;
970 /* If the frame needs to be redrawn,
971 simply forget about any prior mouse highlighting. */
972 if (FRAME_GARBAGED_P (f))
973 hlinfo->mouse_face_window = Qnil;
975 /* (further code for mouse faces ifdef'd out in other terms elided) */
983 ns_update_window_end (struct window *w, bool cursor_on_p,
984 bool mouse_face_overwritten_p)
985 /* --------------------------------------------------------------------------
986 Finished a grouped sequence of drawing calls
987 external (RIF) call; for one window called before update_end
988 -------------------------------------------------------------------------- */
990 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_end");
992 /* note: this fn is nearly identical in all terms */
993 if (!w->pseudo_window_p)
998 display_and_set_cursor (w, 1,
999 w->output_cursor.hpos, w->output_cursor.vpos,
1000 w->output_cursor.x, w->output_cursor.y);
1002 if (draw_window_fringes (w, 1))
1004 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
1005 x_draw_right_divider (w);
1007 x_draw_vertical_border (w);
1013 /* If a row with mouse-face was overwritten, arrange for
1014 frame_up_to_date to redisplay the mouse highlight. */
1015 if (mouse_face_overwritten_p)
1016 reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
1021 ns_update_end (struct frame *f)
1022 /* --------------------------------------------------------------------------
1023 Finished a grouped sequence of drawing calls
1024 external (RIF) call; for whole frame, called after update_window_end
1025 -------------------------------------------------------------------------- */
1027 EmacsView *view = FRAME_NS_VIEW (f);
1029 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end");
1031 /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
1032 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
1037 [[view window] flushWindow];
1040 ns_updating_frame = NULL;
1044 ns_focus (struct frame *f, NSRect *r, int n)
1045 /* --------------------------------------------------------------------------
1046 Internal: Focus on given frame. During small local updates this is used to
1047 draw, however during large updates, ns_update_begin and ns_update_end are
1048 called to wrap the whole thing, in which case these calls are stubbed out.
1049 Except, on GNUstep, we accumulate the rectangle being drawn into, because
1050 the back end won't do this automatically, and will just end up flushing
1052 -------------------------------------------------------------------------- */
1054 NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_focus");
1057 NSTRACE_RECT ("r", *r);
1060 if (f != ns_updating_frame)
1062 NSView *view = FRAME_NS_VIEW (f);
1063 if (view != focus_view)
1065 if (focus_view != NULL)
1067 [focus_view unlockFocus];
1068 [[focus_view window] flushWindow];
1075 /*if (view) debug_lock++; */
1082 [[NSGraphicsContext currentContext] saveGraphicsState];
1084 NSRectClipList (r, 2);
1093 ns_unfocus (struct frame *f)
1094 /* --------------------------------------------------------------------------
1095 Internal: Remove focus on given frame
1096 -------------------------------------------------------------------------- */
1098 NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_unfocus");
1102 [[NSGraphicsContext currentContext] restoreGraphicsState];
1106 if (f != ns_updating_frame)
1108 if (focus_view != NULL)
1110 [focus_view unlockFocus];
1111 [[focus_view window] flushWindow];
1120 ns_clip_to_row (struct window *w, struct glyph_row *row,
1121 enum glyph_row_area area, BOOL gc)
1122 /* --------------------------------------------------------------------------
1123 Internal (but parallels other terms): Focus drawing on given row
1124 -------------------------------------------------------------------------- */
1126 struct frame *f = XFRAME (WINDOW_FRAME (w));
1128 int window_x, window_y, window_width;
1130 window_box (w, area, &window_x, &window_y, &window_width, 0);
1132 clip_rect.origin.x = window_x;
1133 clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
1134 clip_rect.origin.y = max (clip_rect.origin.y, window_y);
1135 clip_rect.size.width = window_width;
1136 clip_rect.size.height = row->visible_height;
1138 ns_focus (f, &clip_rect, 1);
1142 /* ==========================================================================
1144 Visible bell and beep.
1146 ========================================================================== */
1149 @interface EmacsBell : NSImageView
1151 // Number of currently active bell:s.
1152 unsigned int nestCount;
1154 - (void)show:(NSView *)view;
1158 @implementation EmacsBell
1162 if ((self = [super init]))
1165 self.image = [NSImage imageNamed:NSImageNameCaution];
1170 - (void)show:(NSView *)view
1172 NSTRACE ("[EmacsBell show:]");
1173 NSTRACE_MSG ("nestCount: %u", nestCount);
1175 // Show the image, unless it's already shown.
1178 NSRect rect = [view bounds];
1180 pos.x = rect.origin.x + (rect.size.width - self.image.size.width )/2;
1181 pos.y = rect.origin.y + (rect.size.height - self.image.size.height)/2;
1183 [self setFrameOrigin:pos];
1184 [self setFrameSize:self.image.size];
1186 [[[view window] contentView] addSubview:self
1187 positioned:NSWindowAbove
1193 [self performSelector:@selector(hide) withObject:self afterDelay:0.5];
1199 // Note: Trace output from this method isn't shown, reason unknown.
1200 // NSTRACE ("[EmacsBell hide]");
1204 // Remove the image once the last bell became inactive.
1207 [self removeFromSuperview];
1214 ns_ring_bell (struct frame *f)
1215 /* --------------------------------------------------------------------------
1217 -------------------------------------------------------------------------- */
1219 NSTRACE ("ns_ring_bell");
1222 struct frame *frame = SELECTED_FRAME ();
1225 static EmacsBell * bell_view = nil;
1226 if (bell_view == nil)
1228 bell_view = [[EmacsBell alloc] init];
1234 view = FRAME_NS_VIEW (frame);
1237 [bell_view show:view];
1249 /* ==========================================================================
1251 Frame / window manager related functions
1253 ========================================================================== */
1257 ns_raise_frame (struct frame *f)
1258 /* --------------------------------------------------------------------------
1259 Bring window to foreground and make it active
1260 -------------------------------------------------------------------------- */
1264 check_window_system (f);
1265 view = FRAME_NS_VIEW (f);
1267 if (FRAME_VISIBLE_P (f))
1268 [[view window] makeKeyAndOrderFront: NSApp];
1274 ns_lower_frame (struct frame *f)
1275 /* --------------------------------------------------------------------------
1277 -------------------------------------------------------------------------- */
1281 check_window_system (f);
1282 view = FRAME_NS_VIEW (f);
1284 [[view window] orderBack: NSApp];
1290 ns_frame_raise_lower (struct frame *f, bool raise)
1291 /* --------------------------------------------------------------------------
1293 -------------------------------------------------------------------------- */
1295 NSTRACE ("ns_frame_raise_lower");
1305 ns_frame_rehighlight (struct frame *frame)
1306 /* --------------------------------------------------------------------------
1307 External (hook): called on things like window switching within frame
1308 -------------------------------------------------------------------------- */
1310 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
1311 struct frame *old_highlight = dpyinfo->x_highlight_frame;
1313 NSTRACE ("ns_frame_rehighlight");
1314 if (dpyinfo->x_focus_frame)
1316 dpyinfo->x_highlight_frame
1317 = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1318 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1319 : dpyinfo->x_focus_frame);
1320 if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame))
1322 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
1323 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
1327 dpyinfo->x_highlight_frame = 0;
1329 if (dpyinfo->x_highlight_frame &&
1330 dpyinfo->x_highlight_frame != old_highlight)
1334 x_update_cursor (old_highlight, 1);
1335 x_set_frame_alpha (old_highlight);
1337 if (dpyinfo->x_highlight_frame)
1339 x_update_cursor (dpyinfo->x_highlight_frame, 1);
1340 x_set_frame_alpha (dpyinfo->x_highlight_frame);
1347 x_make_frame_visible (struct frame *f)
1348 /* --------------------------------------------------------------------------
1349 External: Show the window (X11 semantics)
1350 -------------------------------------------------------------------------- */
1352 NSTRACE ("x_make_frame_visible");
1353 /* XXX: at some points in past this was not needed, as the only place that
1354 called this (frame.c:Fraise_frame ()) also called raise_lower;
1355 if this ends up the case again, comment this out again. */
1356 if (!FRAME_VISIBLE_P (f))
1358 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1360 SET_FRAME_VISIBLE (f, 1);
1363 /* Making a new frame from a fullscreen frame will make the new frame
1364 fullscreen also. So skip handleFS as this will print an error. */
1365 if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH
1366 && [view isFullscreen])
1369 if (f->want_fullscreen != FULLSCREEN_NONE)
1380 x_make_frame_invisible (struct frame *f)
1381 /* --------------------------------------------------------------------------
1382 External: Hide the window (X11 semantics)
1383 -------------------------------------------------------------------------- */
1386 NSTRACE ("x_make_frame_invisible");
1387 check_window_system (f);
1388 view = FRAME_NS_VIEW (f);
1389 [[view window] orderOut: NSApp];
1390 SET_FRAME_VISIBLE (f, 0);
1391 SET_FRAME_ICONIFIED (f, 0);
1396 x_iconify_frame (struct frame *f)
1397 /* --------------------------------------------------------------------------
1398 External: Iconify window
1399 -------------------------------------------------------------------------- */
1402 struct ns_display_info *dpyinfo;
1404 NSTRACE ("x_iconify_frame");
1405 check_window_system (f);
1406 view = FRAME_NS_VIEW (f);
1407 dpyinfo = FRAME_DISPLAY_INFO (f);
1409 if (dpyinfo->x_highlight_frame == f)
1410 dpyinfo->x_highlight_frame = 0;
1412 if ([[view window] windowNumber] <= 0)
1414 /* the window is still deferred. Make it very small, bring it
1415 on screen and order it out. */
1416 NSRect s = { { 100, 100}, {0, 0} };
1418 t = [[view window] frame];
1419 [[view window] setFrame: s display: NO];
1420 [[view window] orderBack: NSApp];
1421 [[view window] orderOut: NSApp];
1422 [[view window] setFrame: t display: NO];
1424 [[view window] miniaturize: NSApp];
1427 /* Free X resources of frame F. */
1430 x_free_frame_resources (struct frame *f)
1433 struct ns_display_info *dpyinfo;
1434 Mouse_HLInfo *hlinfo;
1436 NSTRACE ("x_free_frame_resources");
1437 check_window_system (f);
1438 view = FRAME_NS_VIEW (f);
1439 dpyinfo = FRAME_DISPLAY_INFO (f);
1440 hlinfo = MOUSE_HL_INFO (f);
1442 [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
1446 free_frame_menubar (f);
1447 free_frame_faces (f);
1449 if (f == dpyinfo->x_focus_frame)
1450 dpyinfo->x_focus_frame = 0;
1451 if (f == dpyinfo->x_highlight_frame)
1452 dpyinfo->x_highlight_frame = 0;
1453 if (f == hlinfo->mouse_face_mouse_frame)
1454 reset_mouse_highlight (hlinfo);
1456 if (f->output_data.ns->miniimage != nil)
1457 [f->output_data.ns->miniimage release];
1459 [[view window] close];
1462 xfree (f->output_data.ns);
1468 x_destroy_window (struct frame *f)
1469 /* --------------------------------------------------------------------------
1470 External: Delete the window
1471 -------------------------------------------------------------------------- */
1473 NSTRACE ("x_destroy_window");
1474 check_window_system (f);
1475 x_free_frame_resources (f);
1481 x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1482 /* --------------------------------------------------------------------------
1483 External: Position the window
1484 -------------------------------------------------------------------------- */
1486 NSView *view = FRAME_NS_VIEW (f);
1487 NSArray *screens = [NSScreen screens];
1488 NSScreen *fscreen = [screens objectAtIndex: 0];
1489 NSScreen *screen = [[view window] screen];
1491 NSTRACE ("x_set_offset");
1498 if (view != nil && screen && fscreen)
1500 f->left_pos = f->size_hint_flags & XNegative
1501 ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
1503 /* We use visibleFrame here to take menu bar into account.
1504 Ideally we should also adjust left/top with visibleFrame.origin. */
1506 f->top_pos = f->size_hint_flags & YNegative
1507 ? ([screen visibleFrame].size.height + f->top_pos
1508 - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
1509 - FRAME_TOOLBAR_HEIGHT (f))
1511 #ifdef NS_IMPL_GNUSTEP
1512 if (f->left_pos < 100)
1513 f->left_pos = 100; /* don't overlap menu */
1515 /* Constrain the setFrameTopLeftPoint so we don't move behind the
1517 NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos),
1518 SCREENMAXBOUND ([fscreen frame].size.height
1520 NSTRACE_POINT ("setFrameTopLeftPoint", pt);
1521 [[view window] setFrameTopLeftPoint: pt];
1522 f->size_hint_flags &= ~(XNegative|YNegative);
1530 x_set_window_size (struct frame *f,
1531 bool change_gravity,
1535 /* --------------------------------------------------------------------------
1536 Adjust window pixel size based on given character grid size
1537 Impl is a bit more complex than other terms, need to do some
1539 -------------------------------------------------------------------------- */
1541 EmacsView *view = FRAME_NS_VIEW (f);
1542 NSWindow *window = [view window];
1543 NSRect wr = [window frame];
1544 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1545 int pixelwidth, pixelheight;
1547 int orig_height = wr.size.height;
1549 NSTRACE ("x_set_window_size");
1554 NSTRACE_RECT ("current", wr);
1555 NSTRACE_MSG ("Width:%d Height:%d Pixelwise:%d", width, height, pixelwise);
1556 NSTRACE_MSG ("Font %d x %d", FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f));
1562 pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
1563 pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
1564 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
1565 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
1569 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
1570 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
1575 /* If we have a toolbar, take its height into account. */
1576 if (tb && ! [view isFullscreen])
1578 /* NOTE: previously this would generate wrong result if toolbar not
1579 yet displayed and fixing toolbar_height=32 helped, but
1580 now (200903) seems no longer needed */
1581 FRAME_TOOLBAR_HEIGHT (f) =
1582 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1583 - FRAME_NS_TITLEBAR_HEIGHT (f);
1585 /* Only breaks things here, removed by martin 2015-09-30. */
1586 #ifdef NS_IMPL_GNUSTEP
1587 FRAME_TOOLBAR_HEIGHT (f) -= 3;
1592 FRAME_TOOLBAR_HEIGHT (f) = 0;
1594 wr.size.width = pixelwidth + f->border_width;
1595 wr.size.height = pixelheight;
1596 if (! [view isFullscreen])
1597 wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f)
1598 + FRAME_TOOLBAR_HEIGHT (f);
1600 /* Do not try to constrain to this screen. We may have multiple
1601 screens, and want Emacs to span those. Constraining to screen
1602 prevents that, and that is not nice to the user. */
1603 if (f->output_data.ns->zooming)
1604 f->output_data.ns->zooming = 0;
1606 wr.origin.y += orig_height - wr.size.height;
1608 frame_size_history_add
1609 (f, Qx_set_window_size_1, width, height,
1610 list5 (Fcons (make_number (pixelwidth), make_number (pixelheight)),
1611 Fcons (make_number (wr.size.width), make_number (wr.size.height)),
1612 make_number (f->border_width),
1613 make_number (FRAME_NS_TITLEBAR_HEIGHT (f)),
1614 make_number (FRAME_TOOLBAR_HEIGHT (f))));
1616 [window setFrame: wr display: YES];
1618 /* This is a trick to compensate for Emacs' managing the scrollbar area
1619 as a fixed number of standard character columns. Instead of leaving
1620 blank space for the extra, we chopped it off above. Now for
1621 left-hand scrollbars, we shift all rendering to the left by the
1622 difference between the real width and Emacs' imagined one. For
1623 right-hand bars, don't worry about it since the extra is never used.
1624 (Obviously doesn't work for vertically split windows tho..) */
1626 NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
1627 ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
1628 - NS_SCROLL_BAR_WIDTH (f), 0)
1629 : NSMakePoint (0, 0);
1631 [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
1632 [view setBoundsOrigin: origin];
1635 [view updateFrameSize: NO];
1641 ns_fullscreen_hook (struct frame *f)
1643 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1645 NSTRACE ("ns_fullscreen_hook");
1647 if (!FRAME_VISIBLE_P (f))
1650 if (! [view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH)
1652 /* Old style fs don't initiate correctly if created from
1653 init/default-frame alist, so use a timer (not nice...).
1655 [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view
1656 selector: @selector (handleFS)
1657 userInfo: nil repeats: NO];
1666 /* ==========================================================================
1670 ========================================================================== */
1674 ns_lookup_indexed_color (unsigned long idx, struct frame *f)
1676 struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
1677 if (idx < 1 || idx >= color_table->avail)
1679 return color_table->colors[idx];
1684 ns_index_color (NSColor *color, struct frame *f)
1686 struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
1690 if (!color_table->colors)
1692 color_table->size = NS_COLOR_CAPACITY;
1693 color_table->avail = 1; /* skip idx=0 as marker */
1694 color_table->colors = xmalloc (color_table->size * sizeof (NSColor *));
1695 color_table->colors[0] = nil;
1696 color_table->empty_indices = [[NSMutableSet alloc] init];
1699 /* Do we already have this color? */
1700 for (i = 1; i < color_table->avail; i++)
1701 if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
1704 if ([color_table->empty_indices count] > 0)
1706 NSNumber *index = [color_table->empty_indices anyObject];
1707 [color_table->empty_indices removeObject: index];
1708 idx = [index unsignedLongValue];
1712 if (color_table->avail == color_table->size)
1713 color_table->colors =
1714 xpalloc (color_table->colors, &color_table->size, 1,
1715 min (ULONG_MAX, PTRDIFF_MAX), sizeof *color_table->colors);
1716 idx = color_table->avail++;
1719 color_table->colors[idx] = color;
1721 /*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1727 ns_free_indexed_color (unsigned long idx, struct frame *f)
1729 struct ns_color_table *color_table;
1736 color_table = FRAME_DISPLAY_INFO (f)->color_table;
1738 if (idx <= 0 || idx >= color_table->size) {
1739 message1 ("ns_free_indexed_color: Color index out of range.\n");
1743 index = [NSNumber numberWithUnsignedInt: idx];
1744 if ([color_table->empty_indices containsObject: index]) {
1745 message1 ("ns_free_indexed_color: attempt to free already freed color.\n");
1749 color = color_table->colors[idx];
1751 color_table->colors[idx] = nil;
1752 [color_table->empty_indices addObject: index];
1753 /*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1758 ns_get_color (const char *name, NSColor **col)
1759 /* --------------------------------------------------------------------------
1761 -------------------------------------------------------------------------- */
1762 /* On *Step, we attempt to mimic the X11 platform here, down to installing an
1763 X11 rgb.txt-compatible color list in Emacs.clr (see ns_term_init()).
1764 See: http://thread.gmane.org/gmane.emacs.devel/113050/focus=113272). */
1767 static char hex[20];
1769 float r = -1.0, g, b;
1770 NSString *nsname = [NSString stringWithUTF8String: name];
1772 NSTRACE ("ns_get_color(%s, **)", name);
1776 if ([nsname isEqualToString: @"ns_selection_bg_color"])
1778 #ifdef NS_IMPL_COCOA
1779 NSString *defname = [[NSUserDefaults standardUserDefaults]
1780 stringForKey: @"AppleHighlightColor"];
1785 if ((new = [NSColor selectedTextBackgroundColor]) != nil)
1787 *col = [new colorUsingDefaultColorSpace];
1792 nsname = NS_SELECTION_BG_COLOR_DEFAULT;
1794 name = [nsname UTF8String];
1796 else if ([nsname isEqualToString: @"ns_selection_fg_color"])
1798 /* NOTE: OSX applications normally don't set foreground selection, but
1799 text may be unreadable if we don't.
1801 if ((new = [NSColor selectedTextColor]) != nil)
1803 *col = [new colorUsingDefaultColorSpace];
1808 nsname = NS_SELECTION_FG_COLOR_DEFAULT;
1809 name = [nsname UTF8String];
1812 /* First, check for some sort of numeric specification. */
1815 if (name[0] == '0' || name[0] == '1' || name[0] == '.') /* RGB decimal */
1817 NSScanner *scanner = [NSScanner scannerWithString: nsname];
1818 [scanner scanFloat: &r];
1819 [scanner scanFloat: &g];
1820 [scanner scanFloat: &b];
1822 else if (!strncmp(name, "rgb:", 4)) /* A newer X11 format -- rgb:r/g/b */
1823 scaling = (snprintf (hex, sizeof hex, "%s", name + 4) - 2) / 3;
1824 else if (name[0] == '#') /* An old X11 format; convert to newer */
1826 int len = (strlen(name) - 1);
1827 int start = (len % 3 == 0) ? 1 : len / 4 + 1;
1829 scaling = strlen(name+start) / 3;
1830 for (i = 0; i < 3; i++)
1831 sprintf (hex + i * (scaling + 1), "%.*s/", scaling,
1832 name + start + i * scaling);
1833 hex[3 * (scaling + 1) - 1] = '\0';
1839 float fscale = scaling == 4 ? 65535.0 : (scaling == 2 ? 255.0 : 15.0);
1840 if (sscanf (hex, "%x/%x/%x", &rr, &gg, &bb))
1850 *col = [NSColor colorForEmacsRed: r green: g blue: b alpha: 1.0];
1855 /* Otherwise, color is expected to be from a list */
1857 NSEnumerator *lenum, *cenum;
1861 #ifdef NS_IMPL_GNUSTEP
1862 /* XXX: who is wrong, the requestor or the implementation? */
1863 if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
1865 nsname = @"highlightColor";
1868 lenum = [[NSColorList availableColorLists] objectEnumerator];
1869 while ( (clist = [lenum nextObject]) && new == nil)
1871 cenum = [[clist allKeys] objectEnumerator];
1872 while ( (name = [cenum nextObject]) && new == nil )
1874 if ([name compare: nsname
1875 options: NSCaseInsensitiveSearch] == NSOrderedSame )
1876 new = [clist colorWithKey: name];
1882 *col = [new colorUsingDefaultColorSpace];
1889 ns_lisp_to_color (Lisp_Object color, NSColor **col)
1890 /* --------------------------------------------------------------------------
1891 Convert a Lisp string object to a NS color
1892 -------------------------------------------------------------------------- */
1894 NSTRACE ("ns_lisp_to_color");
1895 if (STRINGP (color))
1896 return ns_get_color (SSDATA (color), col);
1897 else if (SYMBOLP (color))
1898 return ns_get_color (SSDATA (SYMBOL_NAME (color)), col);
1904 ns_color_to_lisp (NSColor *col)
1905 /* --------------------------------------------------------------------------
1906 Convert a color to a lisp string with the RGB equivalent
1907 -------------------------------------------------------------------------- */
1909 EmacsCGFloat red, green, blue, alpha, gray;
1912 NSTRACE ("ns_color_to_lisp");
1915 if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
1917 if ((str =[[col colorNameComponent] UTF8String]))
1920 return build_string ((char *)str);
1923 [[col colorUsingDefaultColorSpace]
1924 getRed: &red green: &green blue: &blue alpha: &alpha];
1925 if (red == green && red == blue)
1927 [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
1928 getWhite: &gray alpha: &alpha];
1929 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1930 lrint (gray * 0xff), lrint (gray * 0xff), lrint (gray * 0xff));
1932 return build_string (buf);
1935 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1936 lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
1939 return build_string (buf);
1944 ns_query_color(void *col, XColor *color_def, int setPixel)
1945 /* --------------------------------------------------------------------------
1946 Get ARGB values out of NSColor col and put them into color_def.
1947 If setPixel, set the pixel to a concatenated version.
1948 and set color_def pixel to the resulting index.
1949 -------------------------------------------------------------------------- */
1951 EmacsCGFloat r, g, b, a;
1953 [((NSColor *)col) getRed: &r green: &g blue: &b alpha: &a];
1954 color_def->red = r * 65535;
1955 color_def->green = g * 65535;
1956 color_def->blue = b * 65535;
1958 if (setPixel == YES)
1960 = ARGB_TO_ULONG((int)(a*255),
1961 (int)(r*255), (int)(g*255), (int)(b*255));
1966 ns_defined_color (struct frame *f,
1971 /* --------------------------------------------------------------------------
1972 Return true if named color found, and set color_def rgb accordingly.
1973 If makeIndex and alloc are nonzero put the color in the color_table,
1974 and set color_def pixel to the resulting index.
1975 If makeIndex is zero, set color_def pixel to ARGB.
1976 Return false if not found
1977 -------------------------------------------------------------------------- */
1980 NSTRACE_WHEN (NSTRACE_GROUP_COLOR, "ns_defined_color");
1983 if (ns_get_color (name, &col) != 0) /* Color not found */
1988 if (makeIndex && alloc)
1989 color_def->pixel = ns_index_color (col, f);
1990 ns_query_color (col, color_def, !makeIndex);
1997 x_set_frame_alpha (struct frame *f)
1998 /* --------------------------------------------------------------------------
1999 change the entire-frame transparency
2000 -------------------------------------------------------------------------- */
2002 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2004 double alpha_min = 1.0;
2006 NSTRACE ("x_set_frame_alpha");
2008 if (dpyinfo->x_highlight_frame == f)
2009 alpha = f->alpha[0];
2011 alpha = f->alpha[1];
2013 if (FLOATP (Vframe_alpha_lower_limit))
2014 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
2015 else if (INTEGERP (Vframe_alpha_lower_limit))
2016 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
2020 else if (1.0 < alpha)
2022 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
2025 #ifdef NS_IMPL_COCOA
2027 EmacsView *view = FRAME_NS_VIEW (f);
2028 [[view window] setAlphaValue: alpha];
2034 /* ==========================================================================
2038 ========================================================================== */
2042 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
2043 /* --------------------------------------------------------------------------
2044 Programmatically reposition mouse pointer in pixel coordinates
2045 -------------------------------------------------------------------------- */
2047 NSTRACE ("frame_set_mouse_pixel_position");
2050 /* FIXME: this does not work, and what about GNUstep? */
2051 #ifdef NS_IMPL_COCOA
2052 [FRAME_NS_VIEW (f) lockFocus];
2053 PSsetmouse ((float)pix_x, (float)pix_y);
2054 [FRAME_NS_VIEW (f) unlockFocus];
2060 note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y)
2061 /* ------------------------------------------------------------------------
2062 Called by EmacsView on mouseMovement events. Passes on
2063 to emacs mainstream code if we moved off of a rect of interest
2064 known as last_mouse_glyph.
2065 ------------------------------------------------------------------------ */
2067 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2070 // NSTRACE ("note_mouse_movement");
2072 dpyinfo->last_mouse_motion_frame = frame;
2073 r = &dpyinfo->last_mouse_glyph;
2075 /* Note, this doesn't get called for enter/leave, since we don't have a
2076 position. Those are taken care of in the corresponding NSView methods. */
2078 /* has movement gone beyond last rect we were tracking? */
2079 if (x < r->origin.x || x >= r->origin.x + r->size.width
2080 || y < r->origin.y || y >= r->origin.y + r->size.height)
2082 ns_update_begin (frame);
2083 frame->mouse_moved = 1;
2084 note_mouse_highlight (frame, x, y);
2085 remember_mouse_glyph (frame, x, y, r);
2086 ns_update_end (frame);
2095 ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
2096 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
2098 /* --------------------------------------------------------------------------
2099 External (hook): inform emacs about mouse position and hit parts.
2100 If a scrollbar is being dragged, set bar_window, part, x, y, time.
2101 x & y should be position in the scrollbar (the whole bar, not the handle)
2102 and length of scrollbar respectively
2103 -------------------------------------------------------------------------- */
2107 Lisp_Object frame, tail;
2109 struct ns_display_info *dpyinfo;
2111 NSTRACE ("ns_mouse_position");
2115 fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n");
2119 dpyinfo = FRAME_DISPLAY_INFO (*fp);
2123 /* Clear the mouse-moved flag for every frame on this display. */
2124 FOR_EACH_FRAME (tail, frame)
2125 if (FRAME_NS_P (XFRAME (frame))
2126 && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
2127 XFRAME (frame)->mouse_moved = 0;
2129 dpyinfo->last_mouse_scroll_bar = nil;
2130 if (dpyinfo->last_mouse_frame
2131 && FRAME_LIVE_P (dpyinfo->last_mouse_frame))
2132 f = dpyinfo->last_mouse_frame;
2134 f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame : SELECTED_FRAME ();
2136 if (f && FRAME_NS_P (f))
2138 view = FRAME_NS_VIEW (*fp);
2140 position = [[view window] mouseLocationOutsideOfEventStream];
2141 position = [view convertPoint: position fromView: nil];
2142 remember_mouse_glyph (f, position.x, position.y,
2143 &dpyinfo->last_mouse_glyph);
2144 NSTRACE_POINT ("position", position);
2146 if (bar_window) *bar_window = Qnil;
2147 if (part) *part = scroll_bar_above_handle;
2149 if (x) XSETINT (*x, lrint (position.x));
2150 if (y) XSETINT (*y, lrint (position.y));
2152 *time = dpyinfo->last_mouse_movement_time;
2161 ns_frame_up_to_date (struct frame *f)
2162 /* --------------------------------------------------------------------------
2163 External (hook): Fix up mouse highlighting right after a full update.
2164 Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls.
2165 -------------------------------------------------------------------------- */
2167 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_frame_up_to_date");
2171 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2172 if (f == hlinfo->mouse_face_mouse_frame)
2176 note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
2177 hlinfo->mouse_face_mouse_x,
2178 hlinfo->mouse_face_mouse_y);
2187 ns_define_frame_cursor (struct frame *f, Cursor cursor)
2188 /* --------------------------------------------------------------------------
2189 External (RIF): set frame mouse pointer type.
2190 -------------------------------------------------------------------------- */
2192 NSTRACE ("ns_define_frame_cursor");
2193 if (FRAME_POINTER_TYPE (f) != cursor)
2195 EmacsView *view = FRAME_NS_VIEW (f);
2196 FRAME_POINTER_TYPE (f) = cursor;
2197 [[view window] invalidateCursorRectsForView: view];
2198 /* Redisplay assumes this function also draws the changed frame
2199 cursor, but this function doesn't, so do it explicitly. */
2200 x_update_cursor (f, 1);
2206 /* ==========================================================================
2210 ========================================================================== */
2214 ns_convert_key (unsigned code)
2215 /* --------------------------------------------------------------------------
2216 Internal call used by NSView-keyDown.
2217 -------------------------------------------------------------------------- */
2219 const unsigned last_keysym = ARRAYELTS (convert_ns_to_X_keysym);
2221 /* An array would be faster, but less easy to read. */
2222 for (keysym = 0; keysym < last_keysym; keysym += 2)
2223 if (code == convert_ns_to_X_keysym[keysym])
2224 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
2226 /* if decide to use keyCode and Carbon table, use this line:
2227 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
2232 x_get_keysym_name (int keysym)
2233 /* --------------------------------------------------------------------------
2234 Called by keyboard.c. Not sure if the return val is important, except
2236 -------------------------------------------------------------------------- */
2238 static char value[16];
2239 NSTRACE ("x_get_keysym_name");
2240 sprintf (value, "%d", keysym);
2246 /* ==========================================================================
2248 Block drawing operations
2250 ========================================================================== */
2254 ns_redraw_scroll_bars (struct frame *f)
2258 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
2259 NSTRACE ("ns_redraw_scroll_bars");
2260 for (i =[subviews count]-1; i >= 0; i--)
2262 view = [subviews objectAtIndex: i];
2263 if (![view isKindOfClass: [EmacsScroller class]]) continue;
2270 ns_clear_frame (struct frame *f)
2271 /* --------------------------------------------------------------------------
2272 External (hook): Erase the entire frame
2273 -------------------------------------------------------------------------- */
2275 NSView *view = FRAME_NS_VIEW (f);
2278 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame");
2280 /* comes on initial frame because we have
2281 after-make-frame-functions = select-frame */
2282 if (!FRAME_DEFAULT_FACE (f))
2285 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2290 ns_focus (f, &r, 1);
2291 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
2295 /* as of 2006/11 or so this is now needed */
2296 ns_redraw_scroll_bars (f);
2302 ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
2303 /* --------------------------------------------------------------------------
2304 External (RIF): Clear section of frame
2305 -------------------------------------------------------------------------- */
2307 NSRect r = NSMakeRect (x, y, width, height);
2308 NSView *view = FRAME_NS_VIEW (f);
2309 struct face *face = FRAME_DEFAULT_FACE (f);
2314 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area");
2316 r = NSIntersectionRect (r, [view frame]);
2317 ns_focus (f, &r, 1);
2318 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
2327 ns_copy_bits (struct frame *f, NSRect src, NSRect dest)
2329 if (FRAME_NS_VIEW (f))
2331 ns_focus (f, &dest, 1);
2332 [FRAME_NS_VIEW (f) scrollRect: src
2333 by: NSMakeSize (dest.origin.x - src.origin.x,
2334 dest.origin.y - src.origin.y)];
2340 ns_scroll_run (struct window *w, struct run *run)
2341 /* --------------------------------------------------------------------------
2342 External (RIF): Insert or delete n lines at line vpos
2343 -------------------------------------------------------------------------- */
2345 struct frame *f = XFRAME (w->frame);
2346 int x, y, width, height, from_y, to_y, bottom_y;
2348 NSTRACE ("ns_scroll_run");
2350 /* begin copy from other terms */
2351 /* Get frame-relative bounding box of the text display area of W,
2352 without mode lines. Include in this box the left and right
2354 window_box (w, ANY_AREA, &x, &y, &width, &height);
2356 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2357 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2358 bottom_y = y + height;
2362 /* Scrolling up. Make sure we don't copy part of the mode
2363 line at the bottom. */
2364 if (from_y + run->height > bottom_y)
2365 height = bottom_y - from_y;
2367 height = run->height;
2371 /* Scrolling down. Make sure we don't copy over the mode line.
2373 if (to_y + run->height > bottom_y)
2374 height = bottom_y - to_y;
2376 height = run->height;
2378 /* end copy from other terms */
2388 NSRect srcRect = NSMakeRect (x, from_y, width, height);
2389 NSRect dstRect = NSMakeRect (x, to_y, width, height);
2391 ns_copy_bits (f, srcRect , dstRect);
2399 ns_after_update_window_line (struct window *w, struct glyph_row *desired_row)
2400 /* --------------------------------------------------------------------------
2401 External (RIF): preparatory to fringe update after text was updated
2402 -------------------------------------------------------------------------- */
2407 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_after_update_window_line");
2409 /* begin copy from other terms */
2412 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2413 desired_row->redraw_fringe_bitmaps_p = 1;
2415 /* When a window has disappeared, make sure that no rest of
2416 full-width rows stays visible in the internal border. */
2417 if (windows_or_buffers_changed
2418 && desired_row->full_width_p
2419 && (f = XFRAME (w->frame),
2420 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2422 && (height = desired_row->visible_height,
2425 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2428 ns_clear_frame_area (f, 0, y, width, height);
2429 ns_clear_frame_area (f,
2430 FRAME_PIXEL_WIDTH (f) - width,
2438 ns_shift_glyphs_for_insert (struct frame *f,
2439 int x, int y, int width, int height,
2441 /* --------------------------------------------------------------------------
2442 External (RIF): copy an area horizontally, don't worry about clearing src
2443 -------------------------------------------------------------------------- */
2445 NSRect srcRect = NSMakeRect (x, y, width, height);
2446 NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
2448 NSTRACE ("ns_shift_glyphs_for_insert");
2450 ns_copy_bits (f, srcRect, dstRect);
2455 /* ==========================================================================
2457 Character encoding and metrics
2459 ========================================================================== */
2463 ns_compute_glyph_string_overhangs (struct glyph_string *s)
2464 /* --------------------------------------------------------------------------
2465 External (RIF); compute left/right overhang of whole string and set in s
2466 -------------------------------------------------------------------------- */
2468 struct font *font = s->font;
2472 struct font_metrics metrics;
2473 unsigned int codes[2];
2474 codes[0] = *(s->char2b);
2475 codes[1] = *(s->char2b + s->nchars - 1);
2477 font->driver->text_extents (font, codes, 2, &metrics);
2478 s->left_overhang = -metrics.lbearing;
2480 = metrics.rbearing > metrics.width
2481 ? metrics.rbearing - metrics.width : 0;
2485 s->left_overhang = 0;
2486 if (EQ (font->driver->type, Qns))
2487 s->right_overhang = ((struct nsfont_info *)font)->ital ?
2488 FONT_HEIGHT (font) * 0.2 : 0;
2490 s->right_overhang = 0;
2496 /* ==========================================================================
2498 Fringe and cursor drawing
2500 ========================================================================== */
2503 extern int max_used_fringe_bitmap;
2505 ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2506 struct draw_fringe_bitmap_params *p)
2507 /* --------------------------------------------------------------------------
2508 External (RIF); fringe-related
2509 -------------------------------------------------------------------------- */
2511 /* Fringe bitmaps comes in two variants, normal and periodic. A
2512 periodic bitmap is used to create a continuous pattern. Since a
2513 bitmap is rendered one text line at a time, the start offset (dh)
2514 of the bitmap varies. Concretely, this is used for the empty
2517 For a bitmap, "h + dh" is the full height and is always
2518 invariant. For a normal bitmap "dh" is zero.
2520 For example, when the period is three and the full height is 72
2521 the following combinations exists:
2527 struct frame *f = XFRAME (WINDOW_FRAME (w));
2528 struct face *face = p->face;
2529 static EmacsImage **bimgs = NULL;
2530 static int nBimgs = 0;
2532 NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap");
2533 NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d",
2534 p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh);
2536 /* grow bimgs if needed */
2537 if (nBimgs < max_used_fringe_bitmap)
2539 bimgs = xrealloc (bimgs, max_used_fringe_bitmap * sizeof *bimgs);
2540 memset (bimgs + nBimgs, 0,
2541 (max_used_fringe_bitmap - nBimgs) * sizeof *bimgs);
2542 nBimgs = max_used_fringe_bitmap;
2545 /* Must clip because of partially visible lines. */
2546 ns_clip_to_row (w, row, ANY_AREA, YES);
2550 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2552 if (bx >= 0 && nx > 0)
2554 NSRect r = NSMakeRect (bx, by, nx, ny);
2556 [ns_lookup_indexed_color (face->background, f) set];
2563 NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h);
2564 EmacsImage *img = bimgs[p->which - 1];
2568 // Note: For "periodic" images, allocate one EmacsImage for
2569 // the base image, and use it for all dh:s.
2570 unsigned short *bits = p->bits;
2571 int full_height = p->h + p->dh;
2573 unsigned char *cbits = xmalloc (full_height);
2575 for (i = 0; i < full_height; i++)
2577 img = [[EmacsImage alloc] initFromXBM: cbits width: 8
2580 bimgs[p->which - 1] = img;
2584 NSTRACE_RECT ("r", r);
2587 /* Since we composite the bitmap instead of just blitting it, we need
2588 to erase the whole background. */
2589 [ns_lookup_indexed_color(face->background, f) set];
2595 bm_color = ns_lookup_indexed_color(face->foreground, f);
2596 else if (p->overlay_p)
2597 bm_color = ns_lookup_indexed_color(face->background, f);
2599 bm_color = f->output_data.ns->cursor_color;
2600 [img setXBMColor: bm_color];
2603 // Note: For periodic images, the full image height is "h + hd".
2604 // By using the height h, a suitable part of the image is used.
2605 NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
2607 NSTRACE_RECT ("fromRect", fromRect);
2609 #ifdef NS_IMPL_COCOA
2612 operation: NSCompositeSourceOver
2618 NSPoint pt = r.origin;
2620 [img compositeToPoint: pt operation: NSCompositeSourceOver];
2629 ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2630 int x, int y, enum text_cursor_kinds cursor_type,
2631 int cursor_width, bool on_p, bool active_p)
2632 /* --------------------------------------------------------------------------
2633 External call (RIF): draw cursor.
2634 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
2635 -------------------------------------------------------------------------- */
2638 int fx, fy, h, cursor_height;
2639 struct frame *f = WINDOW_XFRAME (w);
2640 struct glyph *phys_cursor_glyph;
2641 struct glyph *cursor_glyph;
2643 NSColor *hollow_color = FRAME_BACKGROUND_COLOR (f);
2645 /* If cursor is out of bounds, don't draw garbage. This can happen
2646 in mini-buffer windows when switching between echo area glyphs
2649 NSTRACE ("ns_draw_window_cursor");
2654 w->phys_cursor_type = cursor_type;
2655 w->phys_cursor_on_p = on_p;
2657 if (cursor_type == NO_CURSOR)
2659 w->phys_cursor_width = 0;
2663 if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
2665 if (glyph_row->exact_window_width_line_p
2666 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
2668 glyph_row->cursor_in_fringe_p = 1;
2669 draw_fringe_bitmap (w, glyph_row, 0);
2674 /* We draw the cursor (with NSRectFill), then draw the glyph on top
2675 (other terminals do it the other way round). We must set
2676 w->phys_cursor_width to the cursor width. For bar cursors, that
2677 is CURSOR_WIDTH; for box cursors, it is the glyph width. */
2678 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
2680 /* The above get_phys_cursor_geometry call set w->phys_cursor_width
2681 to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */
2682 if (cursor_type == BAR_CURSOR)
2684 if (cursor_width < 1)
2685 cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
2686 w->phys_cursor_width = cursor_width;
2688 /* If we have an HBAR, "cursor_width" MAY specify height. */
2689 else if (cursor_type == HBAR_CURSOR)
2691 cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
2692 if (cursor_height > glyph_row->height)
2693 cursor_height = glyph_row->height;
2694 if (h > cursor_height) // Cursor smaller than line height, move down
2695 fy += h - cursor_height;
2699 r.origin.x = fx, r.origin.y = fy;
2701 r.size.width = w->phys_cursor_width;
2703 /* TODO: only needed in rare cases with last-resort font in HELLO..
2704 should we do this more efficiently? */
2705 ns_clip_to_row (w, glyph_row, ANY_AREA, NO); /* do ns_focus(f, &r, 1); if remove */
2708 face = FACE_FROM_ID (f, phys_cursor_glyph->face_id);
2709 if (face && NS_FACE_BACKGROUND (face)
2710 == ns_index_color (FRAME_CURSOR_COLOR (f), f))
2712 [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
2713 hollow_color = FRAME_CURSOR_COLOR (f);
2716 [FRAME_CURSOR_COLOR (f) set];
2718 #ifdef NS_IMPL_COCOA
2719 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
2720 atomic. Cleaner ways of doing this should be investigated.
2721 One way would be to set a global variable DRAWING_CURSOR
2722 when making the call to draw_phys..(), don't focus in that
2723 case, then move the ns_unfocus() here after that call. */
2724 NSDisableScreenUpdates ();
2727 switch (cursor_type)
2729 case DEFAULT_CURSOR:
2732 case FILLED_BOX_CURSOR:
2735 case HOLLOW_BOX_CURSOR:
2738 NSRectFill (NSInsetRect (r, 1, 1));
2739 [FRAME_CURSOR_COLOR (f) set];
2746 /* If the character under cursor is R2L, draw the bar cursor
2747 on the right of its glyph, rather than on the left. */
2748 cursor_glyph = get_phys_cursor_glyph (w);
2749 if ((cursor_glyph->resolved_level & 1) != 0)
2750 s.origin.x += cursor_glyph->pixel_width - s.size.width;
2757 /* draw the character under the cursor */
2758 if (cursor_type != NO_CURSOR)
2759 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2761 #ifdef NS_IMPL_COCOA
2762 NSEnableScreenUpdates ();
2769 ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2770 /* --------------------------------------------------------------------------
2771 External (RIF): Draw a vertical line.
2772 -------------------------------------------------------------------------- */
2774 struct frame *f = XFRAME (WINDOW_FRAME (w));
2776 NSRect r = NSMakeRect (x, y0, 1, y1-y0);
2778 NSTRACE ("ns_draw_vertical_window_border");
2780 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2782 [ns_lookup_indexed_color(face->foreground, f) set];
2784 ns_focus (f, &r, 1);
2791 ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
2792 /* --------------------------------------------------------------------------
2793 External (RIF): Draw a window divider.
2794 -------------------------------------------------------------------------- */
2796 struct frame *f = XFRAME (WINDOW_FRAME (w));
2798 NSRect r = NSMakeRect (x0, y0, x1-x0, y1-y0);
2800 NSTRACE ("ns_draw_window_divider");
2802 face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
2804 [ns_lookup_indexed_color(face->foreground, f) set];
2806 ns_focus (f, &r, 1);
2812 ns_show_hourglass (struct frame *f)
2814 /* TODO: add NSProgressIndicator to all frames. */
2818 ns_hide_hourglass (struct frame *f)
2820 /* TODO: remove NSProgressIndicator from all frames. */
2823 /* ==========================================================================
2825 Glyph drawing operations
2827 ========================================================================== */
2830 ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2831 /* --------------------------------------------------------------------------
2832 Wrapper utility to account for internal border width on full-width lines,
2833 and allow top full-width rows to hit the frame top. nr should be pointer
2834 to two successive NSRects. Number of rects actually used is returned.
2835 -------------------------------------------------------------------------- */
2837 int n = get_glyph_string_clip_rects (s, nr, 2);
2841 /* --------------------------------------------------------------------
2842 Draw a wavy line under glyph string s. The wave fills wave_height
2849 wave_height = 3 | * * * *
2850 --------------------------------------------------------------------- */
2853 ns_draw_underwave (struct glyph_string *s, EmacsCGFloat width, EmacsCGFloat x)
2855 int wave_height = 3, wave_length = 2;
2856 int y, dx, dy, odd, xmax;
2861 dy = wave_height - 1;
2862 y = s->ybase - wave_height + 3;
2865 /* Find and set clipping rectangle */
2866 waveClip = NSMakeRect (x, y, width, wave_height);
2867 [[NSGraphicsContext currentContext] saveGraphicsState];
2868 NSRectClip (waveClip);
2870 /* Draw the waves */
2871 a.x = x - ((int)(x) % dx) + (EmacsCGFloat) 0.5;
2873 odd = (int)(a.x/dx) % 2;
2874 a.y = b.y = y + 0.5;
2883 [NSBezierPath strokeLineFromPoint:a toPoint:b];
2884 a.x = b.x, a.y = b.y;
2885 b.x += dx, b.y = y + 0.5 + odd*dy;
2889 /* Restore previous clipping rectangle(s) */
2890 [[NSGraphicsContext currentContext] restoreGraphicsState];
2896 ns_draw_text_decoration (struct glyph_string *s, struct face *face,
2897 NSColor *defaultCol, CGFloat width, CGFloat x)
2898 /* --------------------------------------------------------------------------
2899 Draw underline, overline, and strike-through on glyph string s.
2900 -------------------------------------------------------------------------- */
2902 if (s->for_overlaps)
2906 if (face->underline_p)
2908 if (s->face->underline_type == FACE_UNDER_WAVE)
2910 if (face->underline_defaulted_p)
2913 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2915 ns_draw_underwave (s, width, x);
2917 else if (s->face->underline_type == FACE_UNDER_LINE)
2921 unsigned long thickness, position;
2923 /* If the prev was underlined, match its appearance. */
2924 if (s->prev && s->prev->face->underline_p
2925 && s->prev->face->underline_type == FACE_UNDER_LINE
2926 && s->prev->underline_thickness > 0)
2928 thickness = s->prev->underline_thickness;
2929 position = s->prev->underline_position;
2934 unsigned long descent;
2937 descent = s->y + s->height - s->ybase;
2939 /* Use underline thickness of font, defaulting to 1. */
2940 thickness = (font && font->underline_thickness > 0)
2941 ? font->underline_thickness : 1;
2943 /* Determine the offset of underlining from the baseline. */
2944 if (x_underline_at_descent_line)
2945 position = descent - thickness;
2946 else if (x_use_underline_position_properties
2947 && font && font->underline_position >= 0)
2948 position = font->underline_position;
2950 position = lround (font->descent / 2);
2952 position = underline_minimum_offset;
2954 position = max (position, underline_minimum_offset);
2956 /* Ensure underlining is not cropped. */
2957 if (descent <= position)
2959 position = descent - 1;
2962 else if (descent < position + thickness)
2966 s->underline_thickness = thickness;
2967 s->underline_position = position;
2969 r = NSMakeRect (x, s->ybase + position, width, thickness);
2971 if (face->underline_defaulted_p)
2974 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2978 /* Do overline. We follow other terms in using a thickness of 1
2979 and ignoring overline_margin. */
2980 if (face->overline_p)
2983 r = NSMakeRect (x, s->y, width, 1);
2985 if (face->overline_color_defaulted_p)
2988 [ns_lookup_indexed_color (face->overline_color, s->f) set];
2992 /* Do strike-through. We follow other terms for thickness and
2993 vertical position.*/
2994 if (face->strike_through_p)
2999 dy = lrint ((s->height - 1) / 2);
3000 r = NSMakeRect (x, s->y + dy, width, 1);
3002 if (face->strike_through_color_defaulted_p)
3005 [ns_lookup_indexed_color (face->strike_through_color, s->f) set];
3011 ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
3012 char left_p, char right_p)
3013 /* --------------------------------------------------------------------------
3014 Draw an unfilled rect inside r, optionally leaving left and/or right open.
3015 Note we can't just use an NSDrawRect command, because of the possibility
3016 of some sides not being drawn, and because the rect will be filled.
3017 -------------------------------------------------------------------------- */
3023 s.size.height = thickness;
3025 s.origin.y += r.size.height - thickness;
3028 s.size.height = r.size.height;
3029 s.origin.y = r.origin.y;
3031 /* left, right (optional) */
3032 s.size.width = thickness;
3037 s.origin.x += r.size.width - thickness;
3044 ns_draw_relief (NSRect r, int thickness, char raised_p,
3045 char top_p, char bottom_p, char left_p, char right_p,
3046 struct glyph_string *s)
3047 /* --------------------------------------------------------------------------
3048 Draw a relief rect inside r, optionally leaving some sides open.
3049 Note we can't just use an NSDrawBezel command, because of the possibility
3050 of some sides not being drawn, and because the rect will be filled.
3051 -------------------------------------------------------------------------- */
3053 static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
3054 NSColor *newBaseCol = nil;
3057 NSTRACE ("ns_draw_relief");
3061 if (s->face->use_box_color_for_shadows_p)
3063 newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f);
3065 /* else if (s->first_glyph->type == IMAGE_GLYPH
3067 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3069 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
3073 newBaseCol = ns_lookup_indexed_color (s->face->background, s->f);
3076 if (newBaseCol == nil)
3077 newBaseCol = [NSColor grayColor];
3079 if (newBaseCol != baseCol) /* TODO: better check */
3082 baseCol = [newBaseCol retain];
3084 lightCol = [[baseCol highlightWithLevel: 0.2] retain];
3086 darkCol = [[baseCol shadowWithLevel: 0.3] retain];
3089 [(raised_p ? lightCol : darkCol) set];
3091 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
3094 sr.size.height = thickness;
3095 if (top_p) NSRectFill (sr);
3098 sr.size.height = r.size.height;
3099 sr.size.width = thickness;
3100 if (left_p) NSRectFill (sr);
3102 [(raised_p ? darkCol : lightCol) set];
3105 sr.size.width = r.size.width;
3106 sr.size.height = thickness;
3107 sr.origin.y += r.size.height - thickness;
3108 if (bottom_p) NSRectFill (sr);
3111 sr.size.height = r.size.height;
3112 sr.origin.y = r.origin.y;
3113 sr.size.width = thickness;
3114 sr.origin.x += r.size.width - thickness;
3115 if (right_p) NSRectFill (sr);
3120 ns_dumpglyphs_box_or_relief (struct glyph_string *s)
3121 /* --------------------------------------------------------------------------
3122 Function modeled after x_draw_glyph_string_box ().
3123 Sets up parameters for drawing.
3124 -------------------------------------------------------------------------- */
3126 int right_x, last_x;
3127 char left_p, right_p;
3128 struct glyph *last_glyph;
3133 if (s->hl == DRAW_MOUSE_FACE)
3135 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3137 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3142 thickness = face->box_line_width;
3144 NSTRACE ("ns_dumpglyphs_box_or_relief");
3146 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3147 ? WINDOW_RIGHT_EDGE_X (s->w)
3148 : window_box_right (s->w, s->area));
3149 last_glyph = (s->cmp || s->img
3150 ? s->first_glyph : s->first_glyph + s->nchars-1);
3152 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
3153 ? last_x - 1 : min (last_x, s->x + s->background_width) - 1));
3155 left_p = (s->first_glyph->left_box_line_p
3156 || (s->hl == DRAW_MOUSE_FACE
3157 && (s->prev == NULL || s->prev->hl != s->hl)));
3158 right_p = (last_glyph->right_box_line_p
3159 || (s->hl == DRAW_MOUSE_FACE
3160 && (s->next == NULL || s->next->hl != s->hl)));
3162 r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
3164 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
3165 if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
3167 ns_draw_box (r, abs (thickness),
3168 ns_lookup_indexed_color (face->box_color, s->f),
3173 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
3174 1, 1, left_p, right_p, s);
3180 ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
3181 /* --------------------------------------------------------------------------
3182 Modeled after x_draw_glyph_string_background, which draws BG in
3183 certain cases. Others are left to the text rendering routine.
3184 -------------------------------------------------------------------------- */
3186 NSTRACE ("ns_maybe_dumpglyphs_background");
3188 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
3190 int box_line_width = max (s->face->box_line_width, 0);
3191 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3192 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
3193 dimensions, since the actual glyphs might be much
3194 smaller. So in that case we always clear the rectangle
3195 with background color. */
3196 || FONT_TOO_HIGH (s->font)
3197 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
3200 if (s->hl == DRAW_MOUSE_FACE)
3202 face = FACE_FROM_ID (s->f,
3203 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3205 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3208 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3210 [(NS_FACE_BACKGROUND (face) != 0
3211 ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
3212 : FRAME_BACKGROUND_COLOR (s->f)) set];
3215 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
3216 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
3219 if (s->hl != DRAW_CURSOR)
3221 NSRect r = NSMakeRect (s->x, s->y + box_line_width,
3222 s->background_width,
3223 s->height-2*box_line_width);
3227 s->background_filled_p = 1;
3234 ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
3235 /* --------------------------------------------------------------------------
3236 Renders an image and associated borders.
3237 -------------------------------------------------------------------------- */
3239 EmacsImage *img = s->img->pixmap;
3240 int box_line_vwidth = max (s->face->box_line_width, 0);
3241 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3242 int bg_x, bg_y, bg_height;
3249 NSTRACE ("ns_dumpglyphs_image");
3251 if (s->face->box != FACE_NO_BOX
3252 && s->first_glyph->left_box_line_p && s->slice.x == 0)
3253 x += abs (s->face->box_line_width);
3256 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
3257 bg_height = s->height;
3258 /* other terms have this, but was causing problems w/tabbar mode */
3259 /* - 2 * box_line_vwidth; */
3261 if (s->slice.x == 0) x += s->img->hmargin;
3262 if (s->slice.y == 0) y += s->img->vmargin;
3264 /* Draw BG: if we need larger area than image itself cleared, do that,
3265 otherwise, since we composite the image under NS (instead of mucking
3266 with its background color), we must clear just the image area. */
3267 if (s->hl == DRAW_MOUSE_FACE)
3269 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3271 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3274 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3276 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set];
3278 if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin
3279 || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width)
3281 br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height);
3282 s->background_filled_p = 1;
3286 br = NSMakeRect (x, y, s->slice.width, s->slice.height);
3291 /* Draw the image.. do we need to draw placeholder if img ==nil? */
3294 #ifdef NS_IMPL_COCOA
3295 NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height);
3296 NSRect ir = NSMakeRect (s->slice.x, s->slice.y,
3297 s->slice.width, s->slice.height);
3300 operation: NSCompositeSourceOver
3305 [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
3306 operation: NSCompositeSourceOver];
3310 if (s->hl == DRAW_CURSOR)
3312 [FRAME_CURSOR_COLOR (s->f) set];
3313 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3314 tdCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3316 /* Currently on NS img->mask is always 0. Since
3317 get_window_cursor_type specifies a hollow box cursor when on
3318 a non-masked image we never reach this clause. But we put it
3319 in in anticipation of better support for image masks on
3321 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3325 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3328 /* Draw underline, overline, strike-through. */
3329 ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x);
3331 /* Draw relief, if requested */
3332 if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
3334 if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
3336 th = tool_bar_button_relief >= 0 ?
3337 tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3338 raised_p = (s->hl == DRAW_IMAGE_RAISED);
3342 th = abs (s->img->relief);
3343 raised_p = (s->img->relief > 0);
3346 r.origin.x = x - th;
3347 r.origin.y = y - th;
3348 r.size.width = s->slice.width + 2*th-1;
3349 r.size.height = s->slice.height + 2*th-1;
3350 ns_draw_relief (r, th, raised_p,
3352 s->slice.y + s->slice.height == s->img->height,
3354 s->slice.x + s->slice.width == s->img->width, s);
3357 /* If there is no mask, the background won't be seen,
3358 so draw a rectangle on the image for the cursor.
3359 Do this for all images, getting transparency right is not reliable. */
3360 if (s->hl == DRAW_CURSOR)
3362 int thickness = abs (s->img->relief);
3363 if (thickness == 0) thickness = 1;
3364 ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
3370 ns_dumpglyphs_stretch (struct glyph_string *s)
3375 NSColor *fgCol, *bgCol;
3377 if (!s->background_filled_p)
3379 n = ns_get_glyph_string_clip_rect (s, r);
3380 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
3382 ns_focus (s->f, r, n);
3384 if (s->hl == DRAW_MOUSE_FACE)
3386 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3388 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3391 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3393 bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3394 fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3396 for (i = 0; i < n; ++i)
3398 if (!s->row->full_width_p)
3400 int overrun, leftoverrun;
3402 /* truncate to avoid overwriting fringe and/or scrollbar */
3403 overrun = max (0, (s->x + s->background_width)
3404 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
3405 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
3406 r[i].size.width -= overrun;
3408 /* truncate to avoid overwriting to left of the window box */
3409 leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
3410 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
3412 if (leftoverrun > 0)
3414 r[i].origin.x += leftoverrun;
3415 r[i].size.width -= leftoverrun;
3418 /* XXX: Try to work between problem where a stretch glyph on
3419 a partially-visible bottom row will clear part of the
3420 modeline, and another where list-buffers headers and similar
3421 rows erroneously have visible_height set to 0. Not sure
3422 where this is coming from as other terms seem not to show. */
3423 r[i].size.height = min (s->height, s->row->visible_height);
3428 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
3429 overwriting cursor (usually when cursor on a tab) */
3430 if (s->hl == DRAW_CURSOR)
3435 width = s->w->phys_cursor_width;
3436 r[i].size.width -= width;
3437 r[i].origin.x += width;
3441 /* Draw overlining, etc. on the cursor. */
3442 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3443 ns_draw_text_decoration (s, face, bgCol, width, x);
3445 ns_draw_text_decoration (s, face, fgCol, width, x);
3452 /* Draw overlining, etc. on the stretch glyph (or the part
3453 of the stretch glyph after the cursor). */
3454 ns_draw_text_decoration (s, face, fgCol, r[i].size.width,
3458 s->background_filled_p = 1;
3464 ns_draw_composite_glyph_string_foreground (struct glyph_string *s)
3467 struct font *font = s->font;
3469 /* If first glyph of S has a left box line, start drawing the text
3470 of S to the right of that box line. */
3471 if (s->face && s->face->box != FACE_NO_BOX
3472 && s->first_glyph->left_box_line_p)
3473 x = s->x + eabs (s->face->box_line_width);
3477 /* S is a glyph string for a composition. S->cmp_from is the index
3478 of the first character drawn for glyphs of this composition.
3479 S->cmp_from == 0 means we are drawing the very first character of
3480 this composition. */
3482 /* Draw a rectangle for the composition if the font for the very
3483 first character of the composition could not be loaded. */
3484 if (s->font_not_found_p)
3486 if (s->cmp_from == 0)
3488 NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1);
3489 ns_draw_box (r, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
3492 else if (! s->first_glyph->u.cmp.automatic)
3496 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
3497 /* TAB in a composition means display glyphs with padding
3498 space on the left or right. */
3499 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
3501 int xx = x + s->cmp->offsets[j * 2];
3502 int yy = y - s->cmp->offsets[j * 2 + 1];
3504 font->driver->draw (s, j, j + 1, xx, yy, false);
3505 if (s->face->overstrike)
3506 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
3511 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
3516 for (i = j = s->cmp_from; i < s->cmp_to; i++)
3518 glyph = LGSTRING_GLYPH (gstring, i);
3519 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
3520 width += LGLYPH_WIDTH (glyph);
3523 int xoff, yoff, wadjust;
3527 font->driver->draw (s, j, i, x, y, false);
3528 if (s->face->overstrike)
3529 font->driver->draw (s, j, i, x + 1, y, false);
3532 xoff = LGLYPH_XOFF (glyph);
3533 yoff = LGLYPH_YOFF (glyph);
3534 wadjust = LGLYPH_WADJUST (glyph);
3535 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
3536 if (s->face->overstrike)
3537 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
3546 font->driver->draw (s, j, i, x, y, false);
3547 if (s->face->overstrike)
3548 font->driver->draw (s, j, i, x + 1, y, false);
3554 ns_draw_glyph_string (struct glyph_string *s)
3555 /* --------------------------------------------------------------------------
3556 External (RIF): Main draw-text call.
3557 -------------------------------------------------------------------------- */
3559 /* TODO (optimize): focus for box and contents draw */
3562 char box_drawn_p = 0;
3563 struct font *font = s->face->font;
3564 if (! font) font = FRAME_FONT (s->f);
3566 NSTRACE_WHEN (NSTRACE_GROUP_GLYPHS, "ns_draw_glyph_string");
3568 if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
3571 struct glyph_string *next;
3573 for (width = 0, next = s->next;
3574 next && width < s->right_overhang;
3575 width += next->width, next = next->next)
3576 if (next->first_glyph->type != IMAGE_GLYPH)
3578 if (next->first_glyph->type != STRETCH_GLYPH)
3580 n = ns_get_glyph_string_clip_rect (s->next, r);
3581 ns_focus (s->f, r, n);
3582 ns_maybe_dumpglyphs_background (s->next, 1);
3587 ns_dumpglyphs_stretch (s->next);
3589 next->num_clips = 0;
3593 if (!s->for_overlaps && s->face->box != FACE_NO_BOX
3594 && (s->first_glyph->type == CHAR_GLYPH
3595 || s->first_glyph->type == COMPOSITE_GLYPH))
3597 n = ns_get_glyph_string_clip_rect (s, r);
3598 ns_focus (s->f, r, n);
3599 ns_maybe_dumpglyphs_background (s, 1);
3600 ns_dumpglyphs_box_or_relief (s);
3605 switch (s->first_glyph->type)
3609 n = ns_get_glyph_string_clip_rect (s, r);
3610 ns_focus (s->f, r, n);
3611 ns_dumpglyphs_image (s, r[0]);
3616 ns_dumpglyphs_stretch (s);
3620 case COMPOSITE_GLYPH:
3621 n = ns_get_glyph_string_clip_rect (s, r);
3622 ns_focus (s->f, r, n);
3624 if (s->for_overlaps || (s->cmp_from > 0
3625 && ! s->first_glyph->u.cmp.automatic))
3626 s->background_filled_p = 1;
3628 ns_maybe_dumpglyphs_background
3629 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3631 flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
3632 (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
3633 (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
3634 NS_DUMPGLYPH_NORMAL));
3636 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3638 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3639 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3640 NS_FACE_FOREGROUND (s->face) = tmp;
3644 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
3647 ns_draw_composite_glyph_string_foreground (s);
3650 (s, s->cmp_from, s->nchars, s->x, s->ybase,
3651 (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
3652 || flags == NS_DUMPGLYPH_MOUSEFACE);
3656 NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0
3657 ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face),
3659 : FRAME_FOREGROUND_COLOR (s->f));
3662 /* Draw underline, overline, strike-through. */
3663 ns_draw_text_decoration (s, s->face, col, s->width, s->x);
3666 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3668 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3669 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3670 NS_FACE_FOREGROUND (s->face) = tmp;
3676 case GLYPHLESS_GLYPH:
3677 n = ns_get_glyph_string_clip_rect (s, r);
3678 ns_focus (s->f, r, n);
3680 if (s->for_overlaps || (s->cmp_from > 0
3681 && ! s->first_glyph->u.cmp.automatic))
3682 s->background_filled_p = 1;
3684 ns_maybe_dumpglyphs_background
3685 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3687 /* Not yet implemented. */
3696 /* Draw box if not done already. */
3697 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
3699 n = ns_get_glyph_string_clip_rect (s, r);
3700 ns_focus (s->f, r, n);
3701 ns_dumpglyphs_box_or_relief (s);
3710 /* ==========================================================================
3714 ========================================================================== */
3718 ns_send_appdefined (int value)
3719 /* --------------------------------------------------------------------------
3720 Internal: post an appdefined event which EmacsApp-sendEvent will
3721 recognize and take as a command to halt the event loop.
3722 -------------------------------------------------------------------------- */
3724 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_send_appdefined(%d)", value);
3726 #ifdef NS_IMPL_GNUSTEP
3727 // GNUstep needs postEvent to happen on the main thread.
3728 if (! [[NSThread currentThread] isMainThread])
3730 EmacsApp *app = (EmacsApp *)NSApp;
3731 app->nextappdefined = value;
3732 [app performSelectorOnMainThread:@selector (sendFromMainThread:)
3739 /* Only post this event if we haven't already posted one. This will end
3740 the [NXApp run] main loop after having processed all events queued at
3743 #ifdef NS_IMPL_COCOA
3744 if (! send_appdefined)
3746 /* OSX 10.10.1 swallows the AppDefined event we are sending ourselves
3747 in certain situations (rapid incoming events).
3748 So check if we have one, if not add one. */
3749 NSEvent *appev = [NSApp nextEventMatchingMask:NSApplicationDefinedMask
3750 untilDate:[NSDate distantPast]
3751 inMode:NSDefaultRunLoopMode
3753 if (! appev) send_appdefined = YES;
3757 if (send_appdefined)
3761 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
3762 send_appdefined = NO;
3764 /* Don't need wakeup timer any more */
3767 [timed_entry invalidate];
3768 [timed_entry release];
3772 nxev = [NSEvent otherEventWithType: NSApplicationDefined
3773 location: NSMakePoint (0, 0)
3776 windowNumber: [[NSApp mainWindow] windowNumber]
3777 context: [NSApp context]
3782 /* Post an application defined event on the event queue. When this is
3783 received the [NXApp run] will return, thus having processed all
3784 events which are currently queued. */
3785 [NSApp postEvent: nxev atStart: NO];
3789 #ifdef HAVE_NATIVE_FS
3793 Lisp_Object frame, tail;
3795 if (ns_last_use_native_fullscreen == ns_use_native_fullscreen)
3798 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
3800 FOR_EACH_FRAME (tail, frame)
3802 struct frame *f = XFRAME (frame);
3805 EmacsView *view = FRAME_NS_VIEW (f);
3806 [view updateCollectionBehavior];
3812 /* GNUstep does not have cancelTracking. */
3813 #ifdef NS_IMPL_COCOA
3814 /* Check if menu open should be canceled or continued as normal. */
3816 ns_check_menu_open (NSMenu *menu)
3818 /* Click in menu bar? */
3819 NSArray *a = [[NSApp mainMenu] itemArray];
3823 if (menu == nil) // Menu tracking ended.
3825 if (menu_will_open_state == MENU_OPENING)
3826 menu_will_open_state = MENU_NONE;
3830 for (i = 0; ! found && i < [a count]; i++)
3831 found = menu == [[a objectAtIndex:i] submenu];
3834 if (menu_will_open_state == MENU_NONE && emacs_event)
3836 NSEvent *theEvent = [NSApp currentEvent];
3837 struct frame *emacsframe = SELECTED_FRAME ();
3839 [menu cancelTracking];
3840 menu_will_open_state = MENU_PENDING;
3841 emacs_event->kind = MENU_BAR_ACTIVATE_EVENT;
3842 EV_TRAILER (theEvent);
3844 CGEventRef ourEvent = CGEventCreate (NULL);
3845 menu_mouse_point = CGEventGetLocation (ourEvent);
3846 CFRelease (ourEvent);
3848 else if (menu_will_open_state == MENU_OPENING)
3850 menu_will_open_state = MENU_NONE;
3855 /* Redo saved menu click if state is MENU_PENDING. */
3857 ns_check_pending_open_menu ()
3859 if (menu_will_open_state == MENU_PENDING)
3861 CGEventSourceRef source
3862 = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
3864 CGEventRef event = CGEventCreateMouseEvent (source,
3865 kCGEventLeftMouseDown,
3867 kCGMouseButtonLeft);
3868 CGEventSetType (event, kCGEventLeftMouseDown);
3869 CGEventPost (kCGHIDEventTap, event);
3873 menu_will_open_state = MENU_OPENING;
3876 #endif /* NS_IMPL_COCOA */
3879 unwind_apploopnr (Lisp_Object not_used)
3882 n_emacs_events_pending = 0;
3883 ns_finish_events ();
3888 ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3889 /* --------------------------------------------------------------------------
3890 External (hook): Post an event to ourself and keep reading events until
3891 we read it back again. In effect process all events which were waiting.
3892 From 21+ we have to manage the event buffer ourselves.
3893 -------------------------------------------------------------------------- */
3895 struct input_event ev;
3898 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_read_socket");
3900 #ifdef HAVE_NATIVE_FS
3904 if ([NSApp modalWindow] != nil)
3907 if (hold_event_q.nr > 0)
3910 for (i = 0; i < hold_event_q.nr; ++i)
3911 kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit);
3912 hold_event_q.nr = 0;
3917 n_emacs_events_pending = 0;
3918 ns_init_events (&ev);
3919 q_event_ptr = hold_quit;
3921 /* we manage autorelease pools by allocate/reallocate each time around
3922 the loop; strict nesting is occasionally violated but seems not to
3923 matter.. earlier methods using full nesting caused major memory leaks */
3924 [outerpool release];
3925 outerpool = [[NSAutoreleasePool alloc] init];
3927 /* If have pending open-file requests, attend to the next one of those. */
3928 if (ns_pending_files && [ns_pending_files count] != 0
3929 && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]])
3931 [ns_pending_files removeObjectAtIndex: 0];
3933 /* Deal with pending service requests. */
3934 else if (ns_pending_service_names && [ns_pending_service_names count] != 0
3936 NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
3937 withArg: [ns_pending_service_args objectAtIndex: 0]])
3939 [ns_pending_service_names removeObjectAtIndex: 0];
3940 [ns_pending_service_args removeObjectAtIndex: 0];
3944 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
3945 /* Run and wait for events. We must always send one NX_APPDEFINED event
3946 to ourself, otherwise [NXApp run] will never exit. */
3947 send_appdefined = YES;
3948 ns_send_appdefined (-1);
3950 if (++apploopnr != 1)
3954 record_unwind_protect (unwind_apploopnr, Qt);
3956 unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */
3959 nevents = n_emacs_events_pending;
3960 n_emacs_events_pending = 0;
3961 ns_finish_events ();
3970 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3971 fd_set *exceptfds, struct timespec const *timeout,
3972 sigset_t const *sigmask)
3973 /* --------------------------------------------------------------------------
3974 Replacement for select, checking for events
3975 -------------------------------------------------------------------------- */
3979 struct input_event event;
3982 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_select");
3984 #ifdef HAVE_NATIVE_FS
3988 if (hold_event_q.nr > 0)
3990 /* We already have events pending. */
3996 for (k = 0; k < nfds+1; k++)
3998 if (readfds && FD_ISSET(k, readfds)) ++nr;
3999 if (writefds && FD_ISSET(k, writefds)) ++nr;
4003 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
4004 return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
4006 [outerpool release];
4007 outerpool = [[NSAutoreleasePool alloc] init];
4010 send_appdefined = YES;
4013 pthread_mutex_lock (&select_mutex);
4018 select_readfds = *readfds;
4019 select_valid += SELECT_HAVE_READ;
4023 select_writefds = *writefds;
4024 select_valid += SELECT_HAVE_WRITE;
4029 select_timeout = *timeout;
4030 select_valid += SELECT_HAVE_TMO;
4033 pthread_mutex_unlock (&select_mutex);
4035 /* Inform fd_handler that select should be called */
4037 emacs_write_sig (selfds[1], &c, 1);
4039 else if (nr == 0 && timeout)
4041 /* No file descriptor, just a timeout, no need to wake fd_handler */
4042 double time = timespectod (*timeout);
4043 timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
4046 @selector (timeout_handler:)
4051 else /* No timeout and no file descriptors, can this happen? */
4053 /* Send appdefined so we exit from the loop */
4054 ns_send_appdefined (-1);
4058 ns_init_events (&event);
4059 if (++apploopnr != 1)
4065 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
4066 record_unwind_protect (unwind_apploopnr, Qt);
4068 unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */
4071 ns_finish_events ();
4072 if (nr > 0 && readfds)
4075 emacs_write_sig (selfds[1], &c, 1);
4079 t = last_appdefined_event_data;
4081 if (t != NO_APPDEFINED_DATA)
4083 last_appdefined_event_data = NO_APPDEFINED_DATA;
4087 /* The NX_APPDEFINED event we received was a timeout. */
4092 /* The NX_APPDEFINED event we received was the result of
4093 at least one real input event arriving. */
4099 /* Received back from select () in fd_handler; copy the results */
4100 pthread_mutex_lock (&select_mutex);
4101 if (readfds) *readfds = select_readfds;
4102 if (writefds) *writefds = select_writefds;
4103 pthread_mutex_unlock (&select_mutex);
4118 /* ==========================================================================
4122 ========================================================================== */
4126 ns_set_vertical_scroll_bar (struct window *window,
4127 int portion, int whole, int position)
4128 /* --------------------------------------------------------------------------
4129 External (hook): Update or add scrollbar
4130 -------------------------------------------------------------------------- */
4134 struct frame *f = XFRAME (WINDOW_FRAME (window));
4135 EmacsView *view = FRAME_NS_VIEW (f);
4137 int window_y, window_height;
4138 int top, left, height, width;
4139 BOOL update_p = YES;
4141 /* optimization; display engine sends WAY too many of these.. */
4142 if (!NILP (window->vertical_scroll_bar))
4144 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4145 if ([bar checkSamePosition: position portion: portion whole: whole])
4147 if (view->scrollbarsNeedingUpdate == 0)
4149 if (!windows_or_buffers_changed)
4153 view->scrollbarsNeedingUpdate--;
4158 NSTRACE ("ns_set_vertical_scroll_bar");
4160 /* Get dimensions. */
4161 window_box (window, ANY_AREA, 0, &window_y, 0, &window_height);
4163 height = window_height;
4164 width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
4165 left = WINDOW_SCROLL_BAR_AREA_X (window);
4167 r = NSMakeRect (left, top, width, height);
4168 /* the parent view is flipped, so we need to flip y value */
4170 r.origin.y = (v.size.height - r.size.height - r.origin.y);
4172 XSETWINDOW (win, window);
4175 /* we want at least 5 lines to display a scrollbar */
4176 if (WINDOW_TOTAL_LINES (window) < 5)
4178 if (!NILP (window->vertical_scroll_bar))
4180 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4181 [bar removeFromSuperview];
4182 wset_vertical_scroll_bar (window, Qnil);
4185 ns_clear_frame_area (f, left, top, width, height);
4190 if (NILP (window->vertical_scroll_bar))
4192 if (width > 0 && height > 0)
4193 ns_clear_frame_area (f, left, top, width, height);
4195 bar = [[EmacsScroller alloc] initFrame: r window: win];
4196 wset_vertical_scroll_bar (window, make_save_ptr (bar));
4202 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4203 oldRect = [bar frame];
4204 r.size.width = oldRect.size.width;
4205 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
4207 if (oldRect.origin.x != r.origin.x)
4208 ns_clear_frame_area (f, left, top, width, height);
4214 [bar setPosition: position portion: portion whole: whole];
4220 ns_set_horizontal_scroll_bar (struct window *window,
4221 int portion, int whole, int position)
4222 /* --------------------------------------------------------------------------
4223 External (hook): Update or add scrollbar
4224 -------------------------------------------------------------------------- */
4228 struct frame *f = XFRAME (WINDOW_FRAME (window));
4229 EmacsView *view = FRAME_NS_VIEW (f);
4231 int top, height, left, width;
4232 int window_x, window_width;
4233 BOOL update_p = YES;
4235 /* optimization; display engine sends WAY too many of these.. */
4236 if (!NILP (window->horizontal_scroll_bar))
4238 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4239 if ([bar checkSamePosition: position portion: portion whole: whole])
4241 if (view->scrollbarsNeedingUpdate == 0)
4243 if (!windows_or_buffers_changed)
4247 view->scrollbarsNeedingUpdate--;
4252 NSTRACE ("ns_set_horizontal_scroll_bar");
4254 /* Get dimensions. */
4255 window_box (window, ANY_AREA, 0, &window_x, &window_width, 0);
4257 width = window_width;
4258 height = WINDOW_CONFIG_SCROLL_BAR_LINES (window) * FRAME_LINE_HEIGHT (f);
4259 top = WINDOW_SCROLL_BAR_AREA_Y (window);
4261 r = NSMakeRect (left, top, width, height);
4262 /* the parent view is flipped, so we need to flip y value */
4264 /* ??????? PXW/scrollbars !!!!!!!!!!!!!!!!!!!! */
4265 r.origin.y = (v.size.height - r.size.height - r.origin.y);
4267 XSETWINDOW (win, window);
4270 if (WINDOW_TOTAL_COLS (window) < 5)
4272 if (!NILP (window->horizontal_scroll_bar))
4274 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4275 [bar removeFromSuperview];
4276 wset_horizontal_scroll_bar (window, Qnil);
4278 ns_clear_frame_area (f, left, top, width, height);
4283 if (NILP (window->horizontal_scroll_bar))
4285 if (width > 0 && height > 0)
4286 ns_clear_frame_area (f, left, top, width, height);
4288 bar = [[EmacsScroller alloc] initFrame: r window: win];
4289 wset_horizontal_scroll_bar (window, make_save_ptr (bar));
4295 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4296 oldRect = [bar frame];
4297 r.size.width = oldRect.size.width;
4298 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
4300 if (oldRect.origin.x != r.origin.x)
4301 ns_clear_frame_area (f, left, top, width, height);
4308 [bar setPosition: position portion: portion whole: whole];
4314 ns_condemn_scroll_bars (struct frame *f)
4315 /* --------------------------------------------------------------------------
4316 External (hook): arrange for all frame's scrollbars to be removed
4317 at next call to judge_scroll_bars, except for those redeemed.
4318 -------------------------------------------------------------------------- */
4322 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
4324 NSTRACE ("ns_condemn_scroll_bars");
4326 for (i =[subviews count]-1; i >= 0; i--)
4328 view = [subviews objectAtIndex: i];
4329 if ([view isKindOfClass: [EmacsScroller class]])
4336 ns_redeem_scroll_bar (struct window *window)
4337 /* --------------------------------------------------------------------------
4338 External (hook): arrange to spare this window's scrollbar
4339 at next call to judge_scroll_bars.
4340 -------------------------------------------------------------------------- */
4343 NSTRACE ("ns_redeem_scroll_bar");
4344 if (!NILP (window->vertical_scroll_bar))
4346 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4350 if (!NILP (window->horizontal_scroll_bar))
4352 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4359 ns_judge_scroll_bars (struct frame *f)
4360 /* --------------------------------------------------------------------------
4361 External (hook): destroy all scrollbars on frame that weren't
4362 redeemed after call to condemn_scroll_bars.
4363 -------------------------------------------------------------------------- */
4367 EmacsView *eview = FRAME_NS_VIEW (f);
4368 NSArray *subviews = [[eview superview] subviews];
4371 NSTRACE ("ns_judge_scroll_bars");
4372 for (i = [subviews count]-1; i >= 0; --i)
4374 view = [subviews objectAtIndex: i];
4375 if (![view isKindOfClass: [EmacsScroller class]]) continue;
4381 [eview updateFrameSize: NO];
4384 /* ==========================================================================
4388 ========================================================================== */
4391 x_display_pixel_height (struct ns_display_info *dpyinfo)
4393 NSArray *screens = [NSScreen screens];
4394 NSEnumerator *enumerator = [screens objectEnumerator];
4399 while ((screen = [enumerator nextObject]) != nil)
4400 frame = NSUnionRect (frame, [screen frame]);
4402 return NSHeight (frame);
4406 x_display_pixel_width (struct ns_display_info *dpyinfo)
4408 NSArray *screens = [NSScreen screens];
4409 NSEnumerator *enumerator = [screens objectEnumerator];
4414 while ((screen = [enumerator nextObject]) != nil)
4415 frame = NSUnionRect (frame, [screen frame]);
4417 return NSWidth (frame);
4421 static Lisp_Object ns_string_to_lispmod (const char *s)
4422 /* --------------------------------------------------------------------------
4423 Convert modifier name to lisp symbol
4424 -------------------------------------------------------------------------- */
4426 if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10))
4428 else if (!strncmp (SSDATA (SYMBOL_NAME (Qsuper)), s, 10))
4430 else if (!strncmp (SSDATA (SYMBOL_NAME (Qcontrol)), s, 10))
4432 else if (!strncmp (SSDATA (SYMBOL_NAME (Qalt)), s, 10))
4434 else if (!strncmp (SSDATA (SYMBOL_NAME (Qhyper)), s, 10))
4436 else if (!strncmp (SSDATA (SYMBOL_NAME (Qnone)), s, 10))
4444 ns_default (const char *parameter, Lisp_Object *result,
4445 Lisp_Object yesval, Lisp_Object noval,
4446 BOOL is_float, BOOL is_modstring)
4447 /* --------------------------------------------------------------------------
4448 Check a parameter value in user's preferences
4449 -------------------------------------------------------------------------- */
4451 const char *value = ns_get_defaults_value (parameter);
4457 if (c_strcasecmp (value, "YES") == 0)
4459 else if (c_strcasecmp (value, "NO") == 0)
4461 else if (is_float && (f = strtod (value, &pos), pos != value))
4462 *result = make_float (f);
4463 else if (is_modstring && value)
4464 *result = ns_string_to_lispmod (value);
4465 else fprintf (stderr,
4466 "Bad value for default \"%s\": \"%s\"\n", parameter, value);
4472 ns_initialize_display_info (struct ns_display_info *dpyinfo)
4473 /* --------------------------------------------------------------------------
4474 Initialize global info and storage for display.
4475 -------------------------------------------------------------------------- */
4477 NSScreen *screen = [NSScreen mainScreen];
4478 NSWindowDepth depth = [screen depth];
4480 dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
4481 dpyinfo->resy = 72.27;
4482 dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
4483 NSColorSpaceFromDepth (depth)]
4484 && ![NSCalibratedWhiteColorSpace isEqualToString:
4485 NSColorSpaceFromDepth (depth)];
4486 dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
4487 dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table);
4488 dpyinfo->color_table->colors = NULL;
4489 dpyinfo->root_window = 42; /* a placeholder.. */
4490 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL;
4491 dpyinfo->n_fonts = 0;
4492 dpyinfo->smallest_font_height = 1;
4493 dpyinfo->smallest_char_width = 1;
4495 reset_mouse_highlight (&dpyinfo->mouse_highlight);
4499 /* This and next define (many of the) public functions in this file. */
4500 /* x_... are generic versions in xdisp.c that we, and other terms, get away
4501 with using despite presence in the "system dependent" redisplay
4502 interface. In addition, many of the ns_ methods have code that is
4503 shared with all terms, indicating need for further refactoring. */
4504 extern frame_parm_handler ns_frame_parm_handlers[];
4505 static struct redisplay_interface ns_redisplay_interface =
4507 ns_frame_parm_handlers,
4511 x_clear_end_of_line,
4513 ns_after_update_window_line,
4514 ns_update_window_begin,
4515 ns_update_window_end,
4516 0, /* flush_display */
4517 x_clear_window_mouse_face,
4518 x_get_glyph_overhangs,
4519 x_fix_overlapping_area,
4520 ns_draw_fringe_bitmap,
4521 0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
4522 0, /* destroy_fringe_bitmap */
4523 ns_compute_glyph_string_overhangs,
4524 ns_draw_glyph_string,
4525 ns_define_frame_cursor,
4526 ns_clear_frame_area,
4527 ns_draw_window_cursor,
4528 ns_draw_vertical_window_border,
4529 ns_draw_window_divider,
4530 ns_shift_glyphs_for_insert,
4537 ns_delete_display (struct ns_display_info *dpyinfo)
4543 /* This function is called when the last frame on a display is deleted. */
4545 ns_delete_terminal (struct terminal *terminal)
4547 struct ns_display_info *dpyinfo = terminal->display_info.ns;
4549 NSTRACE ("ns_delete_terminal");
4551 /* Protect against recursive calls. delete_frame in
4552 delete_terminal calls us back when it deletes our last frame. */
4553 if (!terminal->name)
4558 x_destroy_all_bitmaps (dpyinfo);
4559 ns_delete_display (dpyinfo);
4564 static struct terminal *
4565 ns_create_terminal (struct ns_display_info *dpyinfo)
4566 /* --------------------------------------------------------------------------
4567 Set up use of NS before we make the first connection.
4568 -------------------------------------------------------------------------- */
4570 struct terminal *terminal;
4572 NSTRACE ("ns_create_terminal");
4574 terminal = create_terminal (output_ns, &ns_redisplay_interface);
4576 terminal->display_info.ns = dpyinfo;
4577 dpyinfo->terminal = terminal;
4579 terminal->clear_frame_hook = ns_clear_frame;
4580 terminal->ring_bell_hook = ns_ring_bell;
4581 terminal->update_begin_hook = ns_update_begin;
4582 terminal->update_end_hook = ns_update_end;
4583 terminal->read_socket_hook = ns_read_socket;
4584 terminal->frame_up_to_date_hook = ns_frame_up_to_date;
4585 terminal->mouse_position_hook = ns_mouse_position;
4586 terminal->frame_rehighlight_hook = ns_frame_rehighlight;
4587 terminal->frame_raise_lower_hook = ns_frame_raise_lower;
4588 terminal->fullscreen_hook = ns_fullscreen_hook;
4589 terminal->menu_show_hook = ns_menu_show;
4590 terminal->popup_dialog_hook = ns_popup_dialog;
4591 terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
4592 terminal->set_horizontal_scroll_bar_hook = ns_set_horizontal_scroll_bar;
4593 terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
4594 terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
4595 terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
4596 terminal->delete_frame_hook = x_destroy_window;
4597 terminal->delete_terminal_hook = ns_delete_terminal;
4598 /* Other hooks are NULL by default. */
4604 struct ns_display_info *
4605 ns_term_init (Lisp_Object display_name)
4606 /* --------------------------------------------------------------------------
4607 Start the Application and get things rolling.
4608 -------------------------------------------------------------------------- */
4610 struct terminal *terminal;
4611 struct ns_display_info *dpyinfo;
4612 static int ns_initialized = 0;
4615 if (ns_initialized) return x_display_list;
4620 NSTRACE ("ns_term_init");
4622 [outerpool release];
4623 outerpool = [[NSAutoreleasePool alloc] init];
4625 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
4626 /*GSDebugAllocationActive (YES); */
4630 Fset_input_interrupt_mode (Qnil);
4632 if (selfds[0] == -1)
4634 if (emacs_pipe (selfds) != 0)
4636 fprintf (stderr, "Failed to create pipe: %s\n",
4637 emacs_strerror (errno));
4641 fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
4642 FD_ZERO (&select_readfds);
4643 FD_ZERO (&select_writefds);
4644 pthread_mutex_init (&select_mutex, NULL);
4647 ns_pending_files = [[NSMutableArray alloc] init];
4648 ns_pending_service_names = [[NSMutableArray alloc] init];
4649 ns_pending_service_args = [[NSMutableArray alloc] init];
4651 /* Start app and create the main menu, window, view.
4652 Needs to be here because ns_initialize_display_info () uses AppKit classes.
4653 The view will then ask the NSApp to stop and return to Emacs. */
4654 [EmacsApp sharedApplication];
4657 [NSApp setDelegate: NSApp];
4659 /* Start the select thread. */
4660 [NSThread detachNewThreadSelector:@selector (fd_handler:)
4664 /* debugging: log all notifications */
4665 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
4666 selector: @selector (logNotification:)
4667 name: nil object: nil]; */
4669 dpyinfo = xzalloc (sizeof *dpyinfo);
4671 ns_initialize_display_info (dpyinfo);
4672 terminal = ns_create_terminal (dpyinfo);
4674 terminal->kboard = allocate_kboard (Qns);
4675 /* Don't let the initial kboard remain current longer than necessary.
4676 That would cause problems if a file loaded on startup tries to
4677 prompt in the mini-buffer. */
4678 if (current_kboard == initial_kboard)
4679 current_kboard = terminal->kboard;
4680 terminal->kboard->reference_count++;
4682 dpyinfo->next = x_display_list;
4683 x_display_list = dpyinfo;
4685 dpyinfo->name_list_element = Fcons (display_name, Qnil);
4687 terminal->name = xlispstrdup (display_name);
4691 if (!inhibit_x_resources)
4693 ns_default ("GSFontAntiAlias", &ns_antialias_text,
4696 /* this is a standard variable */
4697 ns_default ("AppleAntiAliasingThreshold", &tmp,
4698 make_float (10.0), make_float (6.0), YES, NO);
4699 ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
4702 NSTRACE_MSG ("Colors");
4705 NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
4709 Lisp_Object color_file, color_map, color;
4713 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4714 Fsymbol_value (intern ("data-directory")));
4716 color_map = Fx_load_color_file (color_file);
4717 if (NILP (color_map))
4718 fatal ("Could not read %s.\n", SDATA (color_file));
4720 cl = [[NSColorList alloc] initWithName: @"Emacs"];
4721 for ( ; CONSP (color_map); color_map = XCDR (color_map))
4723 color = XCAR (color_map);
4724 name = SSDATA (XCAR (color));
4725 c = XINT (XCDR (color));
4727 [NSColor colorForEmacsRed: RED_FROM_ULONG (c) / 255.0
4728 green: GREEN_FROM_ULONG (c) / 255.0
4729 blue: BLUE_FROM_ULONG (c) / 255.0
4731 forKey: [NSString stringWithUTF8String: name]];
4733 [cl writeToFile: nil];
4737 NSTRACE_MSG ("Versions");
4740 #ifdef NS_IMPL_GNUSTEP
4741 Vwindow_system_version = build_string (gnustep_base_version);
4743 /*PSnextrelease (128, c); */
4744 char c[DBL_BUFSIZE_BOUND];
4745 int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber);
4746 Vwindow_system_version = make_unibyte_string (c, len);
4750 delete_keyboard_wait_descriptor (0);
4752 ns_app_name = [[NSProcessInfo processInfo] processName];
4754 /* Set up OS X app menu */
4756 NSTRACE_MSG ("Menu init");
4758 #ifdef NS_IMPL_COCOA
4762 /* set up the application menu */
4763 svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
4764 [svcsMenu setAutoenablesItems: NO];
4765 appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
4766 [appMenu setAutoenablesItems: NO];
4767 mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
4768 dockMenu = [[EmacsMenu alloc] initWithTitle: @""];
4770 [appMenu insertItemWithTitle: @"About Emacs"
4771 action: @selector (orderFrontStandardAboutPanel:)
4774 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
4775 [appMenu insertItemWithTitle: @"Preferences..."
4776 action: @selector (showPreferencesWindow:)
4779 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
4780 item = [appMenu insertItemWithTitle: @"Services"
4781 action: @selector (menuDown:)
4784 [appMenu setSubmenu: svcsMenu forItem: item];
4785 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];
4786 [appMenu insertItemWithTitle: @"Hide Emacs"
4787 action: @selector (hide:)
4790 item = [appMenu insertItemWithTitle: @"Hide Others"
4791 action: @selector (hideOtherApplications:)
4794 [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
4795 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8];
4796 [appMenu insertItemWithTitle: @"Quit Emacs"
4797 action: @selector (terminate:)
4801 item = [mainMenu insertItemWithTitle: ns_app_name
4802 action: @selector (menuDown:)
4805 [mainMenu setSubmenu: appMenu forItem: item];
4806 [dockMenu insertItemWithTitle: @"New Frame"
4807 action: @selector (newFrame:)
4811 [NSApp setMainMenu: mainMenu];
4812 [NSApp setAppleMenu: appMenu];
4813 [NSApp setServicesMenu: svcsMenu];
4814 /* Needed at least on Cocoa, to get dock menu to show windows */
4815 [NSApp setWindowsMenu: [[NSMenu alloc] init]];
4817 [[NSNotificationCenter defaultCenter]
4818 addObserver: mainMenu
4819 selector: @selector (trackingNotification:)
4820 name: NSMenuDidBeginTrackingNotification object: mainMenu];
4821 [[NSNotificationCenter defaultCenter]
4822 addObserver: mainMenu
4823 selector: @selector (trackingNotification:)
4824 name: NSMenuDidEndTrackingNotification object: mainMenu];
4826 #endif /* MAC OS X menu setup */
4828 /* Register our external input/output types, used for determining
4829 applicable services and also drag/drop eligibility. */
4831 NSTRACE_MSG ("Input/output types");
4833 ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
4834 ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
4836 ns_drag_types = [[NSArray arrayWithObjects:
4838 NSTabularTextPboardType,
4839 NSFilenamesPboardType,
4840 NSURLPboardType, nil] retain];
4842 /* If fullscreen is in init/default-frame-alist, focus isn't set
4843 right for fullscreen windows, so set this. */
4844 [NSApp activateIgnoringOtherApps:YES];
4846 NSTRACE_MSG ("Call NSApp run");
4849 ns_do_open_file = YES;
4851 #ifdef NS_IMPL_GNUSTEP
4852 /* GNUstep steals SIGCHLD for use in NSTask, but we don't use NSTask.
4853 We must re-catch it so subprocess works. */
4854 catch_child_signal ();
4857 NSTRACE_MSG ("ns_term_init done");
4866 ns_term_shutdown (int sig)
4868 [[NSUserDefaults standardUserDefaults] synchronize];
4870 /* code not reached in emacs.c after this is called by shut_down_emacs: */
4871 if (STRINGP (Vauto_save_list_file_name))
4872 unlink (SSDATA (Vauto_save_list_file_name));
4874 if (sig == 0 || sig == SIGTERM)
4876 [NSApp terminate: NSApp];
4878 else // force a stack trace to happen
4885 /* ==========================================================================
4887 EmacsApp implementation
4889 ========================================================================== */
4892 @implementation EmacsApp
4896 NSTRACE ("[EmacsApp init]");
4898 if ((self = [super init]))
4900 #ifdef NS_IMPL_COCOA
4901 self->isFirst = YES;
4903 #ifdef NS_IMPL_GNUSTEP
4904 self->applicationDidFinishLaunchingCalled = NO;
4911 #ifdef NS_IMPL_COCOA
4914 NSTRACE ("[EmacsApp run]");
4916 #ifndef NSAppKitVersionNumber10_9
4917 #define NSAppKitVersionNumber10_9 1265
4920 if ((int)NSAppKitVersionNumber != NSAppKitVersionNumber10_9)
4926 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4928 if (isFirst) [self finishLaunching];
4931 shouldKeepRunning = YES;
4935 pool = [[NSAutoreleasePool alloc] init];
4938 [self nextEventMatchingMask:NSAnyEventMask
4939 untilDate:[NSDate distantFuture]
4940 inMode:NSDefaultRunLoopMode
4943 [self sendEvent:event];
4944 [self updateWindows];
4945 } while (shouldKeepRunning);
4950 - (void)stop: (id)sender
4952 NSTRACE ("[EmacsApp stop:]");
4954 shouldKeepRunning = NO;
4955 // Stop possible dialog also. Noop if no dialog present.
4956 // The file dialog still leaks 7k - 10k on 10.9 though.
4957 [super stop:sender];
4959 #endif /* NS_IMPL_COCOA */
4961 - (void)logNotification: (NSNotification *)notification
4963 NSTRACE ("[EmacsApp logNotification:]");
4965 const char *name = [[notification name] UTF8String];
4966 if (!strstr (name, "Update") && !strstr (name, "NSMenu")
4967 && !strstr (name, "WindowNumber"))
4968 NSLog (@"notification: '%@'", [notification name]);
4972 - (void)sendEvent: (NSEvent *)theEvent
4973 /* --------------------------------------------------------------------------
4974 Called when NSApp is running for each event received. Used to stop
4975 the loop when we choose, since there's no way to just run one iteration.
4976 -------------------------------------------------------------------------- */
4978 int type = [theEvent type];
4979 NSWindow *window = [theEvent window];
4981 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsApp sendEvent:]");
4982 NSTRACE_MSG ("Type: %d", type);
4984 #ifdef NS_IMPL_GNUSTEP
4985 // Keyboard events aren't propagated to file dialogs for some reason.
4986 if ([NSApp modalWindow] != nil &&
4987 (type == NSKeyDown || type == NSKeyUp || type == NSFlagsChanged))
4989 [[NSApp modalWindow] sendEvent: theEvent];
4994 if (represented_filename != nil && represented_frame)
4996 NSString *fstr = represented_filename;
4997 NSView *view = FRAME_NS_VIEW (represented_frame);
4998 #ifdef NS_IMPL_COCOA
4999 /* work around a bug observed on 10.3 and later where
5000 setTitleWithRepresentedFilename does not clear out previous state
5001 if given filename does not exist */
5002 if (! [[NSFileManager defaultManager] fileExistsAtPath: fstr])
5003 [[view window] setRepresentedFilename: @""];
5005 [[view window] setRepresentedFilename: fstr];
5006 [represented_filename release];
5007 represented_filename = nil;
5008 represented_frame = NULL;
5011 if (type == NSApplicationDefined)
5013 switch ([theEvent data2])
5015 #ifdef NS_IMPL_COCOA
5016 case NSAPP_DATA2_RUNASSCRIPT:
5021 case NSAPP_DATA2_RUNFILEDIALOG:
5022 ns_run_file_dialog ();
5028 if (type == NSCursorUpdate && window == nil)
5030 fprintf (stderr, "Dropping external cursor update event.\n");
5034 if (type == NSApplicationDefined)
5036 /* Events posted by ns_send_appdefined interrupt the run loop here.
5037 But, if a modal window is up, an appdefined can still come through,
5038 (e.g., from a makeKeyWindow event) but stopping self also stops the
5039 modal loop. Just defer it until later. */
5040 if ([NSApp modalWindow] == nil)
5042 last_appdefined_event_data = [theEvent data1];
5047 send_appdefined = YES;
5052 #ifdef NS_IMPL_COCOA
5053 /* If no dialog and none of our frames have focus and it is a move, skip it.
5054 It is a mouse move in an auxiliary menu, i.e. on the top right on OSX,
5055 such as Wifi, sound, date or similar.
5056 This prevents "spooky" highlighting in the frame under the menu. */
5057 if (type == NSMouseMoved && [NSApp modalWindow] == nil)
5059 struct ns_display_info *di;
5060 BOOL has_focus = NO;
5061 for (di = x_display_list; ! has_focus && di; di = di->next)
5062 has_focus = di->x_focus_frame != 0;
5068 NSTRACE_UNSILENCE();
5070 [super sendEvent: theEvent];
5074 - (void)showPreferencesWindow: (id)sender
5076 struct frame *emacsframe = SELECTED_FRAME ();
5077 NSEvent *theEvent = [NSApp currentEvent];
5081 emacs_event->kind = NS_NONKEY_EVENT;
5082 emacs_event->code = KEY_NS_SHOW_PREFS;
5083 emacs_event->modifiers = 0;
5084 EV_TRAILER (theEvent);
5088 - (void)newFrame: (id)sender
5090 NSTRACE ("[EmacsApp newFrame:]");
5092 struct frame *emacsframe = SELECTED_FRAME ();
5093 NSEvent *theEvent = [NSApp currentEvent];
5097 emacs_event->kind = NS_NONKEY_EVENT;
5098 emacs_event->code = KEY_NS_NEW_FRAME;
5099 emacs_event->modifiers = 0;
5100 EV_TRAILER (theEvent);
5104 /* Open a file (used by below, after going into queue read by ns_read_socket) */
5105 - (BOOL) openFile: (NSString *)fileName
5107 NSTRACE ("[EmacsApp openFile:]");
5109 struct frame *emacsframe = SELECTED_FRAME ();
5110 NSEvent *theEvent = [NSApp currentEvent];
5115 emacs_event->kind = NS_NONKEY_EVENT;
5116 emacs_event->code = KEY_NS_OPEN_FILE_LINE;
5117 ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
5118 ns_input_line = Qnil; /* can be start or cons start,end */
5119 emacs_event->modifiers =0;
5120 EV_TRAILER (theEvent);
5126 /* **************************************************************************
5128 EmacsApp delegate implementation
5130 ************************************************************************** */
5132 - (void)applicationDidFinishLaunching: (NSNotification *)notification
5133 /* --------------------------------------------------------------------------
5134 When application is loaded, terminate event loop in ns_term_init
5135 -------------------------------------------------------------------------- */
5137 NSTRACE ("[EmacsApp applicationDidFinishLaunching:]");
5139 #ifdef NS_IMPL_GNUSTEP
5140 ((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES;
5142 [NSApp setServicesProvider: NSApp];
5144 [self antialiasThresholdDidChange:nil];
5145 #ifdef NS_IMPL_COCOA
5146 [[NSNotificationCenter defaultCenter]
5148 selector:@selector(antialiasThresholdDidChange:)
5149 name:NSAntialiasThresholdChangedNotification
5153 ns_send_appdefined (-2);
5156 - (void)antialiasThresholdDidChange:(NSNotification *)notification
5158 #ifdef NS_IMPL_COCOA
5159 macfont_update_antialias_threshold ();
5164 /* Termination sequences:
5167 MenuBar | File | Exit:
5168 Select Quit from App menubar:
5170 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
5173 Select Quit from Dock menu:
5176 Cancel -> Nothing else
5180 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
5185 - (void) terminate: (id)sender
5187 NSTRACE ("[EmacsApp terminate:]");
5189 struct frame *emacsframe = SELECTED_FRAME ();
5194 emacs_event->kind = NS_NONKEY_EVENT;
5195 emacs_event->code = KEY_NS_POWER_OFF;
5196 emacs_event->arg = Qt; /* mark as non-key event */
5197 EV_TRAILER ((id)nil);
5201 runAlertPanel(NSString *title,
5202 NSString *msgFormat,
5203 NSString *defaultButton,
5204 NSString *alternateButton)
5206 #if !defined (NS_IMPL_COCOA) || \
5207 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
5208 return NSRunAlertPanel(title, msgFormat, defaultButton, alternateButton, nil)
5209 == NSAlertDefaultReturn;
5211 NSAlert *alert = [[NSAlert alloc] init];
5212 [alert setAlertStyle: NSCriticalAlertStyle];
5213 [alert setMessageText: msgFormat];
5214 [alert addButtonWithTitle: defaultButton];
5215 [alert addButtonWithTitle: alternateButton];
5216 NSInteger ret = [alert runModal];
5218 return ret == NSAlertFirstButtonReturn;
5223 - (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
5225 NSTRACE ("[EmacsApp applicationShouldTerminate:]");
5229 if (NILP (ns_confirm_quit)) // || ns_shutdown_properly --> TO DO
5230 return NSTerminateNow;
5232 ret = runAlertPanel(ns_app_name,
5233 @"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?",
5234 @"Save Buffers and Exit", @"Cancel");
5237 return NSTerminateNow;
5239 return NSTerminateCancel;
5240 return NSTerminateNow; /* just in case */
5244 not_in_argv (NSString *arg)
5247 const char *a = [arg UTF8String];
5248 for (k = 1; k < initial_argc; ++k)
5249 if (strcmp (a, initial_argv[k]) == 0) return 0;
5253 /* Notification from the Workspace to open a file */
5254 - (BOOL)application: sender openFile: (NSString *)file
5256 if (ns_do_open_file || not_in_argv (file))
5257 [ns_pending_files addObject: file];
5262 /* Open a file as a temporary file */
5263 - (BOOL)application: sender openTempFile: (NSString *)file
5265 if (ns_do_open_file || not_in_argv (file))
5266 [ns_pending_files addObject: file];
5271 /* Notification from the Workspace to open a file noninteractively (?) */
5272 - (BOOL)application: sender openFileWithoutUI: (NSString *)file
5274 if (ns_do_open_file || not_in_argv (file))
5275 [ns_pending_files addObject: file];
5279 /* Notification from the Workspace to open multiple files */
5280 - (void)application: sender openFiles: (NSArray *)fileList
5282 NSEnumerator *files = [fileList objectEnumerator];
5284 /* Don't open files from the command line unconditionally,
5285 Cocoa parses the command line wrong, --option value tries to open value
5286 if --option is the last option. */
5287 while ((file = [files nextObject]) != nil)
5288 if (ns_do_open_file || not_in_argv (file))
5289 [ns_pending_files addObject: file];
5291 [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
5296 /* Handle dock menu requests. */
5297 - (NSMenu *)applicationDockMenu: (NSApplication *) sender
5303 /* TODO: these may help w/IO switching btwn terminal and NSApp */
5304 - (void)applicationWillBecomeActive: (NSNotification *)notification
5306 NSTRACE ("[EmacsApp applicationWillBecomeActive:]");
5307 //ns_app_active=YES;
5310 - (void)applicationDidBecomeActive: (NSNotification *)notification
5312 NSTRACE ("[EmacsApp applicationDidBecomeActive:]");
5314 #ifdef NS_IMPL_GNUSTEP
5315 if (! applicationDidFinishLaunchingCalled)
5316 [self applicationDidFinishLaunching:notification];
5318 //ns_app_active=YES;
5320 ns_update_auto_hide_menu_bar ();
5321 // No constraining takes place when the application is not active.
5322 ns_constrain_all_frames ();
5324 - (void)applicationDidResignActive: (NSNotification *)notification
5326 NSTRACE ("[EmacsApp applicationDidResignActive:]");
5329 ns_send_appdefined (-1);
5334 /* ==========================================================================
5336 EmacsApp aux handlers for managing event loop
5338 ========================================================================== */
5341 - (void)timeout_handler: (NSTimer *)timedEntry
5342 /* --------------------------------------------------------------------------
5343 The timeout specified to ns_select has passed.
5344 -------------------------------------------------------------------------- */
5346 /*NSTRACE ("timeout_handler"); */
5347 ns_send_appdefined (-2);
5350 #ifdef NS_IMPL_GNUSTEP
5351 - (void)sendFromMainThread:(id)unused
5353 ns_send_appdefined (nextappdefined);
5357 - (void)fd_handler:(id)unused
5358 /* --------------------------------------------------------------------------
5359 Check data waiting on file descriptors and terminate if so
5360 -------------------------------------------------------------------------- */
5363 int waiting = 1, nfds;
5366 fd_set readfds, writefds, *wfds;
5367 struct timespec timeout, *tmo;
5368 NSAutoreleasePool *pool = nil;
5370 /* NSTRACE ("fd_handler"); */
5375 pool = [[NSAutoreleasePool alloc] init];
5381 FD_SET (selfds[0], &fds);
5382 result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
5383 if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
5388 pthread_mutex_lock (&select_mutex);
5391 if (select_valid & SELECT_HAVE_READ)
5392 readfds = select_readfds;
5396 if (select_valid & SELECT_HAVE_WRITE)
5398 writefds = select_writefds;
5403 if (select_valid & SELECT_HAVE_TMO)
5405 timeout = select_timeout;
5411 pthread_mutex_unlock (&select_mutex);
5413 FD_SET (selfds[0], &readfds);
5414 if (selfds[0] >= nfds) nfds = selfds[0]+1;
5416 result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL);
5419 ns_send_appdefined (-2);
5420 else if (result > 0)
5422 if (FD_ISSET (selfds[0], &readfds))
5424 if (read (selfds[0], &c, 1) == 1 && c == 's')
5429 pthread_mutex_lock (&select_mutex);
5430 if (select_valid & SELECT_HAVE_READ)
5431 select_readfds = readfds;
5432 if (select_valid & SELECT_HAVE_WRITE)
5433 select_writefds = writefds;
5434 if (select_valid & SELECT_HAVE_TMO)
5435 select_timeout = timeout;
5436 pthread_mutex_unlock (&select_mutex);
5438 ns_send_appdefined (result);
5448 /* ==========================================================================
5452 ========================================================================== */
5454 /* called from system: queue for next pass through event loop */
5455 - (void)requestService: (NSPasteboard *)pboard
5456 userData: (NSString *)userData
5457 error: (NSString **)error
5459 [ns_pending_service_names addObject: userData];
5460 [ns_pending_service_args addObject: [NSString stringWithUTF8String:
5461 SSDATA (ns_string_from_pasteboard (pboard))]];
5465 /* called from ns_read_socket to clear queue */
5466 - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
5468 struct frame *emacsframe = SELECTED_FRAME ();
5469 NSEvent *theEvent = [NSApp currentEvent];
5471 NSTRACE ("[EmacsApp fulfillService:withArg:]");
5476 emacs_event->kind = NS_NONKEY_EVENT;
5477 emacs_event->code = KEY_NS_SPI_SERVICE_CALL;
5478 ns_input_spi_name = build_string ([name UTF8String]);
5479 ns_input_spi_arg = build_string ([arg UTF8String]);
5480 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5481 EV_TRAILER (theEvent);
5491 /* ==========================================================================
5493 EmacsView implementation
5495 ========================================================================== */
5498 @implementation EmacsView
5500 /* needed to inform when window closed from LISP */
5501 - (void) setWindowClosing: (BOOL)closing
5503 NSTRACE ("[EmacsView setWindowClosing:%d]", closing);
5505 windowClosing = closing;
5511 NSTRACE ("[EmacsView dealloc]");
5513 if (fs_state == FULLSCREEN_BOTH)
5514 [nonfs_window release];
5519 /* called on font panel selection */
5520 - (void)changeFont: (id)sender
5522 NSEvent *e = [[self window] currentEvent];
5523 struct face *face = FRAME_DEFAULT_FACE (emacsframe);
5524 struct font *font = face->font;
5529 NSTRACE ("[EmacsView changeFont:]");
5534 #ifdef NS_IMPL_GNUSTEP
5535 nsfont = ((struct nsfont_info *)font)->nsfont;
5537 #ifdef NS_IMPL_COCOA
5538 nsfont = (NSFont *) macfont_get_nsctfont (font);
5541 if ((newFont = [sender convertFont: nsfont]))
5543 SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
5545 emacs_event->kind = NS_NONKEY_EVENT;
5546 emacs_event->modifiers = 0;
5547 emacs_event->code = KEY_NS_CHANGE_FONT;
5549 size = [newFont pointSize];
5550 ns_input_fontsize = make_number (lrint (size));
5551 ns_input_font = build_string ([[newFont familyName] UTF8String]);
5557 - (BOOL)acceptsFirstResponder
5559 NSTRACE ("[EmacsView acceptsFirstResponder]");
5564 - (void)resetCursorRects
5566 NSRect visible = [self visibleRect];
5567 NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
5568 NSTRACE ("[EmacsView resetCursorRects]");
5570 if (currentCursor == nil)
5571 currentCursor = [NSCursor arrowCursor];
5573 if (!NSIsEmptyRect (visible))
5574 [self addCursorRect: visible cursor: currentCursor];
5575 [currentCursor setOnMouseEntered: YES];
5580 /*****************************************************************************/
5581 /* Keyboard handling. */
5584 - (void)keyDown: (NSEvent *)theEvent
5586 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
5588 unsigned fnKeysym = 0;
5589 static NSMutableArray *nsEvArray;
5591 unsigned int flags = [theEvent modifierFlags];
5593 NSTRACE ("[EmacsView keyDown:]");
5595 /* Rhapsody and OS X give up and down events for the arrow keys */
5596 if (ns_fake_keydown == YES)
5597 ns_fake_keydown = NO;
5598 else if ([theEvent type] != NSKeyDown)
5604 if (![[self window] isKeyWindow]
5605 && [[theEvent window] isKindOfClass: [EmacsWindow class]]
5606 /* we must avoid an infinite loop here. */
5607 && (EmacsView *)[[theEvent window] delegate] != self)
5609 /* XXX: There is an occasional condition in which, when Emacs display
5610 updates a different frame from the current one, and temporarily
5611 selects it, then processes some interrupt-driven input
5612 (dispnew.c:3878), OS will send the event to the correct NSWindow, but
5613 for some reason that window has its first responder set to the NSView
5614 most recently updated (I guess), which is not the correct one. */
5615 [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
5619 if (nsEvArray == nil)
5620 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
5622 [NSCursor setHiddenUntilMouseMoves: YES];
5624 if (hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
5626 clear_mouse_face (hlinfo);
5627 hlinfo->mouse_face_hidden = 1;
5630 if (!processingCompose)
5632 /* When using screen sharing, no left or right information is sent,
5633 so use Left key in those cases. */
5634 int is_left_key, is_right_key;
5636 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
5637 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
5639 /* (Carbon way: [theEvent keyCode]) */
5641 /* is it a "function key"? */
5642 /* Note: Sometimes a plain key will have the NSNumericPadKeyMask
5643 flag set (this is probably a bug in the OS).
5645 if (code < 0x00ff && (flags&NSNumericPadKeyMask))
5647 fnKeysym = ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask);
5651 fnKeysym = ns_convert_key (code);
5656 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
5657 because Emacs treats Delete and KP-Delete same (in simple.el). */
5658 if ((fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33)
5659 #ifdef NS_IMPL_GNUSTEP
5660 /* GNUstep uses incompatible keycodes, even for those that are
5661 supposed to be hardware independent. Just check for delete.
5662 Keypad delete does not have keysym 0xFFFF.
5663 See http://savannah.gnu.org/bugs/?25395
5665 || (fnKeysym == 0xFFFF && code == 127)
5668 code = 0xFF08; /* backspace */
5673 /* are there modifiers? */
5674 emacs_event->modifiers = 0;
5676 if (flags & NSHelpKeyMask)
5677 emacs_event->modifiers |= hyper_modifier;
5679 if (flags & NSShiftKeyMask)
5680 emacs_event->modifiers |= shift_modifier;
5682 is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask;
5683 is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
5684 || (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask);
5687 emacs_event->modifiers |= parse_solitary_modifier
5688 (EQ (ns_right_command_modifier, Qleft)
5689 ? ns_command_modifier
5690 : ns_right_command_modifier);
5694 emacs_event->modifiers |= parse_solitary_modifier
5695 (ns_command_modifier);
5697 /* if super (default), take input manager's word so things like
5698 dvorak / qwerty layout work */
5699 if (EQ (ns_command_modifier, Qsuper)
5701 && [[theEvent characters] length] != 0)
5703 /* XXX: the code we get will be unshifted, so if we have
5704 a shift modifier, must convert ourselves */
5705 if (!(flags & NSShiftKeyMask))
5706 code = [[theEvent characters] characterAtIndex: 0];
5708 /* this is ugly and also requires linking w/Carbon framework
5709 (for LMGetKbdType) so for now leave this rare (?) case
5710 undealt with.. in future look into CGEvent methods */
5713 long smv = GetScriptManagerVariable (smKeyScript);
5714 Handle uchrHandle = GetResource
5715 ('uchr', GetScriptVariable (smv, smScriptKeys));
5717 UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle,
5718 [[theEvent characters] characterAtIndex: 0],
5719 kUCKeyActionDisplay,
5720 (flags & ~NSCommandKeyMask) >> 8,
5721 LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask,
5722 &dummy, 1, &dummy, &code);
5729 is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask;
5730 is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask
5731 || (! is_right_key && (flags & NSControlKeyMask) == NSControlKeyMask);
5734 emacs_event->modifiers |= parse_solitary_modifier
5735 (EQ (ns_right_control_modifier, Qleft)
5736 ? ns_control_modifier
5737 : ns_right_control_modifier);
5740 emacs_event->modifiers |= parse_solitary_modifier
5741 (ns_control_modifier);
5743 if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
5744 emacs_event->modifiers |=
5745 parse_solitary_modifier (ns_function_modifier);
5747 left_is_none = NILP (ns_alternate_modifier)
5748 || EQ (ns_alternate_modifier, Qnone);
5750 is_right_key = (flags & NSRightAlternateKeyMask)
5751 == NSRightAlternateKeyMask;
5752 is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
5754 && (flags & NSAlternateKeyMask) == NSAlternateKeyMask);
5758 if ((NILP (ns_right_alternate_modifier)
5759 || EQ (ns_right_alternate_modifier, Qnone)
5760 || (EQ (ns_right_alternate_modifier, Qleft) && left_is_none))
5762 { /* accept pre-interp alt comb */
5763 if ([[theEvent characters] length] > 0)
5764 code = [[theEvent characters] characterAtIndex: 0];
5765 /*HACK: clear lone shift modifier to stop next if from firing */
5766 if (emacs_event->modifiers == shift_modifier)
5767 emacs_event->modifiers = 0;
5770 emacs_event->modifiers |= parse_solitary_modifier
5771 (EQ (ns_right_alternate_modifier, Qleft)
5772 ? ns_alternate_modifier
5773 : ns_right_alternate_modifier);
5776 if (is_left_key) /* default = meta */
5778 if (left_is_none && !fnKeysym)
5779 { /* accept pre-interp alt comb */
5780 if ([[theEvent characters] length] > 0)
5781 code = [[theEvent characters] characterAtIndex: 0];
5782 /*HACK: clear lone shift modifier to stop next if from firing */
5783 if (emacs_event->modifiers == shift_modifier)
5784 emacs_event->modifiers = 0;
5787 emacs_event->modifiers |=
5788 parse_solitary_modifier (ns_alternate_modifier);
5792 fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",
5793 code, fnKeysym, flags, emacs_event->modifiers);
5795 /* if it was a function key or had modifiers, pass it directly to emacs */
5796 if (fnKeysym || (emacs_event->modifiers
5797 && (emacs_event->modifiers != shift_modifier)
5798 && [[theEvent charactersIgnoringModifiers] length] > 0))
5799 /*[[theEvent characters] length] */
5801 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5803 code |= (1<<28)|(3<<16);
5804 else if (code == 0x7f)
5805 code |= (1<<28)|(3<<16);
5807 emacs_event->kind = code > 0xFF
5808 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5810 emacs_event->code = code;
5811 EV_TRAILER (theEvent);
5812 processingCompose = NO;
5818 if (NS_KEYLOG && !processingCompose)
5819 fprintf (stderr, "keyDown: Begin compose sequence.\n");
5821 processingCompose = YES;
5822 [nsEvArray addObject: theEvent];
5823 [self interpretKeyEvents: nsEvArray];
5824 [nsEvArray removeObject: theEvent];
5828 #ifdef NS_IMPL_COCOA
5829 /* Needed to pick up Ctrl-tab and possibly other events that OS X has
5830 decided not to send key-down for.
5831 See http://osdir.com/ml/editors.vim.mac/2007-10/msg00141.html
5832 This only applies on Tiger and earlier.
5833 If it matches one of these, send it on to keyDown. */
5834 -(void)keyUp: (NSEvent *)theEvent
5836 int flags = [theEvent modifierFlags];
5837 int code = [theEvent keyCode];
5839 NSTRACE ("[EmacsView keyUp:]");
5841 if (floor (NSAppKitVersionNumber) <= 824 /*NSAppKitVersionNumber10_4*/ &&
5842 code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask))
5845 fprintf (stderr, "keyUp: passed test");
5846 ns_fake_keydown = YES;
5847 [self keyDown: theEvent];
5853 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
5856 /* <NSTextInput>: called when done composing;
5857 NOTE: also called when we delete over working text, followed immed.
5858 by doCommandBySelector: deleteBackward: */
5859 - (void)insertText: (id)aString
5862 int len = [(NSString *)aString length];
5865 NSTRACE ("[EmacsView insertText:]");
5868 NSLog (@"insertText '%@'\tlen = %d", aString, len);
5869 processingCompose = NO;
5874 /* first, clear any working text */
5875 if (workingText != nil)
5876 [self deleteWorkingText];
5878 /* now insert the string as keystrokes */
5879 for (i =0; i<len; i++)
5881 code = [aString characterAtIndex: i];
5882 /* TODO: still need this? */
5884 code = '~'; /* 0x7E */
5885 if (code != 32) /* Space */
5886 emacs_event->modifiers = 0;
5888 = code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5889 emacs_event->code = code;
5890 EV_TRAILER ((id)nil);
5895 /* <NSTextInput>: inserts display of composing characters */
5896 - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
5898 NSString *str = [aString respondsToSelector: @selector (string)] ?
5899 [aString string] : aString;
5901 NSTRACE ("[EmacsView setMarkedText:selectedRange:]");
5904 NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu",
5905 str, (unsigned long)[str length],
5906 (unsigned long)selRange.length,
5907 (unsigned long)selRange.location);
5909 if (workingText != nil)
5910 [self deleteWorkingText];
5911 if ([str length] == 0)
5917 processingCompose = YES;
5918 workingText = [str copy];
5919 ns_working_text = build_string ([workingText UTF8String]);
5921 emacs_event->kind = NS_TEXT_EVENT;
5922 emacs_event->code = KEY_NS_PUT_WORKING_TEXT;
5923 EV_TRAILER ((id)nil);
5927 /* delete display of composing characters [not in <NSTextInput>] */
5928 - (void)deleteWorkingText
5930 NSTRACE ("[EmacsView deleteWorkingText]");
5932 if (workingText == nil)
5935 NSLog(@"deleteWorkingText len =%lu\n", (unsigned long)[workingText length]);
5936 [workingText release];
5938 processingCompose = NO;
5943 emacs_event->kind = NS_TEXT_EVENT;
5944 emacs_event->code = KEY_NS_UNPUT_WORKING_TEXT;
5945 EV_TRAILER ((id)nil);
5949 - (BOOL)hasMarkedText
5951 NSTRACE ("[EmacsView hasMarkedText]");
5953 return workingText != nil;
5957 - (NSRange)markedRange
5959 NSTRACE ("[EmacsView markedRange]");
5961 NSRange rng = workingText != nil
5962 ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
5964 NSLog (@"markedRange request");
5971 NSTRACE ("[EmacsView unmarkText]");
5974 NSLog (@"unmark (accept) text");
5975 [self deleteWorkingText];
5976 processingCompose = NO;
5980 /* used to position char selection windows, etc. */
5981 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
5985 struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
5987 NSTRACE ("[EmacsView firstRectForCharacterRange:]");
5990 NSLog (@"firstRectForCharRange request");
5992 rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
5993 rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
5994 pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x);
5995 pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y
5996 +FRAME_LINE_HEIGHT (emacsframe));
5998 pt = [self convertPoint: pt toView: nil];
5999 pt = [[self window] convertBaseToScreen: pt];
6005 - (NSInteger)conversationIdentifier
6007 return (NSInteger)self;
6011 - (void)doCommandBySelector: (SEL)aSelector
6013 NSTRACE ("[EmacsView doCommandBySelector:]");
6016 NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
6018 processingCompose = NO;
6019 if (aSelector == @selector (deleteBackward:))
6021 /* happens when user backspaces over an ongoing composition:
6022 throw a 'delete' into the event queue */
6025 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
6026 emacs_event->code = 0xFF08;
6027 EV_TRAILER ((id)nil);
6031 - (NSArray *)validAttributesForMarkedText
6033 static NSArray *arr = nil;
6034 if (arr == nil) arr = [NSArray new];
6035 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
6039 - (NSRange)selectedRange
6042 NSLog (@"selectedRange request");
6043 return NSMakeRange (NSNotFound, 0);
6046 #if defined (NS_IMPL_COCOA) || GNUSTEP_GUI_MAJOR_VERSION > 0 || \
6047 GNUSTEP_GUI_MINOR_VERSION > 22
6048 - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
6050 - (unsigned int)characterIndexForPoint: (NSPoint)thePoint
6054 NSLog (@"characterIndexForPoint request");
6058 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
6060 static NSAttributedString *str = nil;
6061 if (str == nil) str = [NSAttributedString new];
6063 NSLog (@"attributedSubstringFromRange request");
6067 /* End <NSTextInput> impl. */
6068 /*****************************************************************************/
6071 /* This is what happens when the user presses a mouse button. */
6072 - (void)mouseDown: (NSEvent *)theEvent
6074 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6075 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
6077 NSTRACE ("[EmacsView mouseDown:]");
6079 [self deleteWorkingText];
6084 dpyinfo->last_mouse_frame = emacsframe;
6085 /* appears to be needed to prevent spurious movement events generated on
6087 emacsframe->mouse_moved = 0;
6089 if ([theEvent type] == NSScrollWheel)
6091 CGFloat delta = [theEvent deltaY];
6092 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
6095 delta = [theEvent deltaX];
6098 NSTRACE_MSG ("deltaIsZero");
6101 emacs_event->kind = HORIZ_WHEEL_EVENT;
6104 emacs_event->kind = WHEEL_EVENT;
6106 emacs_event->code = 0;
6107 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
6108 ((delta > 0) ? up_modifier : down_modifier);
6112 emacs_event->kind = MOUSE_CLICK_EVENT;
6113 emacs_event->code = EV_BUTTON (theEvent);
6114 emacs_event->modifiers = EV_MODIFIERS (theEvent)
6115 | EV_UDMODIFIERS (theEvent);
6117 XSETINT (emacs_event->x, lrint (p.x));
6118 XSETINT (emacs_event->y, lrint (p.y));
6119 EV_TRAILER (theEvent);
6123 - (void)rightMouseDown: (NSEvent *)theEvent
6125 NSTRACE ("[EmacsView rightMouseDown:]");
6126 [self mouseDown: theEvent];
6130 - (void)otherMouseDown: (NSEvent *)theEvent
6132 NSTRACE ("[EmacsView otherMouseDown:]");
6133 [self mouseDown: theEvent];
6137 - (void)mouseUp: (NSEvent *)theEvent
6139 NSTRACE ("[EmacsView mouseUp:]");
6140 [self mouseDown: theEvent];
6144 - (void)rightMouseUp: (NSEvent *)theEvent
6146 NSTRACE ("[EmacsView rightMouseUp:]");
6147 [self mouseDown: theEvent];
6151 - (void)otherMouseUp: (NSEvent *)theEvent
6153 NSTRACE ("[EmacsView otherMouseUp:]");
6154 [self mouseDown: theEvent];
6158 - (void) scrollWheel: (NSEvent *)theEvent
6160 NSTRACE ("[EmacsView scrollWheel:]");
6161 [self mouseDown: theEvent];
6165 /* Tell emacs the mouse has moved. */
6166 - (void)mouseMoved: (NSEvent *)e
6168 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
6169 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6173 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]");
6175 dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e);
6176 pt = [self convertPoint: [e locationInWindow] fromView: nil];
6177 dpyinfo->last_mouse_motion_x = pt.x;
6178 dpyinfo->last_mouse_motion_y = pt.y;
6180 /* update any mouse face */
6181 if (hlinfo->mouse_face_hidden)
6183 hlinfo->mouse_face_hidden = 0;
6184 clear_mouse_face (hlinfo);
6187 /* tooltip handling */
6188 previous_help_echo_string = help_echo_string;
6189 help_echo_string = Qnil;
6191 if (!NILP (Vmouse_autoselect_window))
6193 NSTRACE_MSG ("mouse_autoselect_window");
6194 static Lisp_Object last_mouse_window;
6196 = window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0);
6198 if (WINDOWP (window)
6199 && !EQ (window, last_mouse_window)
6200 && !EQ (window, selected_window)
6201 && (focus_follows_mouse
6202 || (EQ (XWINDOW (window)->frame,
6203 XWINDOW (selected_window)->frame))))
6205 NSTRACE_MSG ("in_window");
6206 emacs_event->kind = SELECT_WINDOW_EVENT;
6207 emacs_event->frame_or_window = window;
6210 /* Remember the last window where we saw the mouse. */
6211 last_mouse_window = window;
6214 if (!note_mouse_movement (emacsframe, pt.x, pt.y))
6215 help_echo_string = previous_help_echo_string;
6217 XSETFRAME (frame, emacsframe);
6218 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
6220 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
6221 (note_mouse_highlight), which is called through the
6222 note_mouse_movement () call above */
6223 any_help_event_p = YES;
6224 gen_help_event (help_echo_string, frame, help_echo_window,
6225 help_echo_object, help_echo_pos);
6228 if (emacsframe->mouse_moved && send_appdefined)
6229 ns_send_appdefined (-1);
6233 - (void)mouseDragged: (NSEvent *)e
6235 NSTRACE ("[EmacsView mouseDragged:]");
6236 [self mouseMoved: e];
6240 - (void)rightMouseDragged: (NSEvent *)e
6242 NSTRACE ("[EmacsView rightMouseDragged:]");
6243 [self mouseMoved: e];
6247 - (void)otherMouseDragged: (NSEvent *)e
6249 NSTRACE ("[EmacsView otherMouseDragged:]");
6250 [self mouseMoved: e];
6254 - (BOOL)windowShouldClose: (id)sender
6256 NSEvent *e =[[self window] currentEvent];
6258 NSTRACE ("[EmacsView windowShouldClose:]");
6259 windowClosing = YES;
6262 emacs_event->kind = DELETE_WINDOW_EVENT;
6263 emacs_event->modifiers = 0;
6264 emacs_event->code = 0;
6266 /* Don't close this window, let this be done from lisp code. */
6270 - (void) updateFrameSize: (BOOL) delay;
6272 NSWindow *window = [self window];
6273 NSRect wr = [window frame];
6275 int oldc = cols, oldr = rows;
6276 int oldw = FRAME_PIXEL_WIDTH (emacsframe);
6277 int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
6280 NSTRACE ("[EmacsView updateFrameSize:]");
6281 NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
6282 NSTRACE_RECT ("Original frame", wr);
6283 NSTRACE_MSG ("Original columns: %d", cols);
6284 NSTRACE_MSG ("Original rows: %d", rows);
6286 if (! [self isFullscreen])
6288 #ifdef NS_IMPL_GNUSTEP
6289 // GNUstep does not always update the tool bar height. Force it.
6290 if (toolbar && [toolbar isVisible])
6291 update_frame_tool_bar (emacsframe);
6294 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
6295 + FRAME_TOOLBAR_HEIGHT (emacsframe);
6298 if (wait_for_tool_bar)
6300 if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0)
6302 NSTRACE_MSG ("Waiting for toolbar");
6305 wait_for_tool_bar = NO;
6308 neww = (int)wr.size.width - emacsframe->border_width;
6309 newh = (int)wr.size.height - extra;
6311 NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
6312 NSTRACE_MSG ("tool_bar_height: %d", emacsframe->tool_bar_height);
6314 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww);
6315 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh);
6317 if (cols < MINWIDTH)
6320 if (rows < MINHEIGHT)
6323 NSTRACE_MSG ("New columns: %d", cols);
6324 NSTRACE_MSG ("New rows: %d", rows);
6326 if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
6328 NSView *view = FRAME_NS_VIEW (emacsframe);
6329 NSWindow *win = [view window];
6331 change_frame_size (emacsframe,
6332 FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
6333 FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
6335 SET_FRAME_GARBAGED (emacsframe);
6336 cancel_mouse_face (emacsframe);
6338 wr = NSMakeRect (0, 0, neww, newh);
6340 [view setFrame: wr];
6342 // to do: consider using [NSNotificationCenter postNotificationName:].
6343 [self windowDidMove: // Update top/left.
6344 [NSNotification notificationWithName:NSWindowDidMoveNotification
6345 object:[view window]]];
6349 NSTRACE_MSG ("No change");
6353 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
6354 /* normalize frame to gridded text size */
6358 NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]",
6359 NSTRACE_ARG_SIZE (frameSize));
6360 NSTRACE_RECT ("[sender frame]", [sender frame]);
6361 NSTRACE_FSTYPE ("fs_state", fs_state);
6363 if (fs_state == FULLSCREEN_MAXIMIZED
6364 && (maximized_width != (int)frameSize.width
6365 || maximized_height != (int)frameSize.height))
6366 [self setFSValue: FULLSCREEN_NONE];
6367 else if (fs_state == FULLSCREEN_WIDTH
6368 && maximized_width != (int)frameSize.width)
6369 [self setFSValue: FULLSCREEN_NONE];
6370 else if (fs_state == FULLSCREEN_HEIGHT
6371 && maximized_height != (int)frameSize.height)
6372 [self setFSValue: FULLSCREEN_NONE];
6374 if (fs_state == FULLSCREEN_NONE)
6375 maximized_width = maximized_height = -1;
6377 if (! [self isFullscreen])
6379 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
6380 + FRAME_TOOLBAR_HEIGHT (emacsframe);
6383 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, frameSize.width);
6384 if (cols < MINWIDTH)
6387 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe,
6388 frameSize.height - extra);
6389 if (rows < MINHEIGHT)
6391 #ifdef NS_IMPL_COCOA
6393 /* this sets window title to have size in it; the wm does this under GS */
6394 NSRect r = [[self window] frame];
6395 if (r.size.height == frameSize.height && r.size.width == frameSize.width)
6403 else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize)
6406 NSWindow *window = [self window];
6409 char *t = strdup ([[[self window] title] UTF8String]);
6410 char *pos = strstr (t, " — ");
6415 size_title = xmalloc (strlen (old_title) + 40);
6416 esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
6417 [window setTitle: [NSString stringWithUTF8String: size_title]];
6422 #endif /* NS_IMPL_COCOA */
6424 NSTRACE_MSG ("cols: %d rows: %d", cols, rows);
6426 /* Restrict the new size to the text gird.
6428 Don't restrict the width if the user only adjusted the height, and
6429 vice versa. (Without this, the frame would shrink, and move
6430 slightly, if the window was resized by dragging one of its
6432 if (!frame_resize_pixelwise)
6434 NSRect r = [[self window] frame];
6436 if (r.size.width != frameSize.width)
6439 FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols);
6442 if (r.size.height != frameSize.height)
6445 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows) + extra;
6449 NSTRACE_RETURN_SIZE (frameSize);
6455 - (void)windowDidResize: (NSNotification *)notification
6457 NSTRACE ("[EmacsView windowDidResize:]");
6458 if (!FRAME_LIVE_P (emacsframe))
6460 NSTRACE_MSG ("Ignored (frame dead)");
6463 if (emacsframe->output_data.ns->in_animation)
6465 NSTRACE_MSG ("Ignored (in animation)");
6469 if (! [self fsIsNative])
6471 NSWindow *theWindow = [notification object];
6472 /* We can get notification on the non-FS window when in
6474 if ([self window] != theWindow) return;
6477 NSTRACE_RECT ("frame", [[notification object] frame]);
6479 #ifdef NS_IMPL_GNUSTEP
6480 NSWindow *theWindow = [notification object];
6482 /* In GNUstep, at least currently, it's possible to get a didResize
6483 without getting a willResize.. therefore we need to act as if we got
6484 the willResize now */
6485 NSSize sz = [theWindow frame].size;
6486 sz = [self windowWillResize: theWindow toSize: sz];
6487 #endif /* NS_IMPL_GNUSTEP */
6489 if (cols > 0 && rows > 0)
6491 [self updateFrameSize: YES];
6494 ns_send_appdefined (-1);
6497 #ifdef NS_IMPL_COCOA
6498 - (void)viewDidEndLiveResize
6500 NSTRACE ("[EmacsView viewDidEndLiveResize]");
6502 [super viewDidEndLiveResize];
6505 [[self window] setTitle: [NSString stringWithUTF8String: old_title]];
6509 maximizing_resize = NO;
6511 #endif /* NS_IMPL_COCOA */
6514 - (void)windowDidBecomeKey: (NSNotification *)notification
6515 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
6517 [self windowDidBecomeKey];
6521 - (void)windowDidBecomeKey /* for direct calls */
6523 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6524 struct frame *old_focus = dpyinfo->x_focus_frame;
6526 NSTRACE ("[EmacsView windowDidBecomeKey]");
6528 if (emacsframe != old_focus)
6529 dpyinfo->x_focus_frame = emacsframe;
6531 ns_frame_rehighlight (emacsframe);
6535 emacs_event->kind = FOCUS_IN_EVENT;
6536 EV_TRAILER ((id)nil);
6541 - (void)windowDidResignKey: (NSNotification *)notification
6542 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
6544 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6545 BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe;
6546 NSTRACE ("[EmacsView windowDidResignKey:]");
6549 dpyinfo->x_focus_frame = 0;
6551 emacsframe->mouse_moved = 0;
6552 ns_frame_rehighlight (emacsframe);
6554 /* FIXME: for some reason needed on second and subsequent clicks away
6555 from sole-frame Emacs to get hollow box to show */
6556 if (!windowClosing && [[self window] isVisible] == YES)
6558 x_update_cursor (emacsframe, 1);
6559 x_set_frame_alpha (emacsframe);
6562 if (any_help_event_p)
6565 XSETFRAME (frame, emacsframe);
6566 help_echo_string = Qnil;
6567 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
6570 if (emacs_event && is_focus_frame)
6572 [self deleteWorkingText];
6573 emacs_event->kind = FOCUS_OUT_EVENT;
6574 EV_TRAILER ((id)nil);
6579 - (void)windowWillMiniaturize: sender
6581 NSTRACE ("[EmacsView windowWillMiniaturize:]");
6585 - (void)setFrame:(NSRect)frameRect;
6587 NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]",
6588 NSTRACE_ARG_RECT (frameRect));
6590 [super setFrame:(NSRect)frameRect];
6606 - initFrameFromEmacs: (struct frame *)f
6614 NSTRACE ("[EmacsView initFrameFromEmacs:]");
6615 NSTRACE_MSG ("cols:%d lines:%d\n", f->text_cols, f->text_lines);
6618 processingCompose = NO;
6619 scrollbarsNeedingUpdate = 0;
6620 fs_state = FULLSCREEN_NONE;
6621 fs_before_fs = next_maximized = -1;
6622 #ifdef HAVE_NATIVE_FS
6623 fs_is_native = ns_use_native_fullscreen;
6627 maximized_width = maximized_height = -1;
6630 ns_userRect = NSMakeRect (0, 0, 0, 0);
6631 r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
6632 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
6633 [self initWithFrame: r];
6634 [self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
6636 FRAME_NS_VIEW (f) = self;
6638 #ifdef NS_IMPL_COCOA
6640 maximizing_resize = NO;
6643 win = [[EmacsWindow alloc]
6644 initWithContentRect: r
6645 styleMask: (NSResizableWindowMask |
6646 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
6647 NSTitledWindowMask |
6649 NSMiniaturizableWindowMask |
6650 NSClosableWindowMask)
6651 backing: NSBackingStoreBuffered
6654 #ifdef HAVE_NATIVE_FS
6655 [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
6659 bwidth = f->border_width = wr.size.width - r.size.width;
6660 tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
6662 [win setAcceptsMouseMovedEvents: YES];
6663 [win setDelegate: self];
6664 #if !defined (NS_IMPL_COCOA) || \
6665 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
6666 [win useOptimizedDrawing: YES];
6669 [[win contentView] addSubview: self];
6672 [self registerForDraggedTypes: ns_drag_types];
6675 name = [NSString stringWithUTF8String:
6676 NILP (tem) ? "Emacs" : SSDATA (tem)];
6677 [win setTitle: name];
6679 /* toolbar support */
6680 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
6681 [NSString stringWithFormat: @"Emacs Frame %d",
6683 [win setToolbar: toolbar];
6684 [toolbar setVisible: NO];
6686 /* Don't set frame garbaged until tool bar is up to date?
6687 This avoids an extra clear and redraw (flicker) at frame creation. */
6688 if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES;
6689 else wait_for_tool_bar = NO;
6692 #ifdef NS_IMPL_COCOA
6694 NSButton *toggleButton;
6695 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
6696 [toggleButton setTarget: self];
6697 [toggleButton setAction: @selector (toggleToolbar: )];
6700 FRAME_TOOLBAR_HEIGHT (f) = 0;
6704 [win setMiniwindowTitle:
6705 [NSString stringWithUTF8String: SSDATA (tem)]];
6708 NSScreen *screen = [win screen];
6712 NSPoint pt = NSMakePoint
6713 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
6714 IN_BOUND (-SCREENMAX,
6715 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX));
6717 [win setFrameTopLeftPoint: pt];
6719 NSTRACE_RECT ("new frame", [win frame]);
6723 [win makeFirstResponder: self];
6725 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
6726 (FRAME_DEFAULT_FACE (emacsframe)), emacsframe);
6727 [win setBackgroundColor: col];
6728 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
6729 [win setOpaque: NO];
6731 #if !defined (NS_IMPL_COCOA) || \
6732 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
6733 [self allocateGState];
6735 [NSApp registerServicesMenuSendTypes: ns_send_types
6743 - (void)windowDidMove: sender
6745 NSWindow *win = [self window];
6746 NSRect r = [win frame];
6747 NSArray *screens = [NSScreen screens];
6748 NSScreen *screen = [screens objectAtIndex: 0];
6750 NSTRACE ("[EmacsView windowDidMove:]");
6752 if (!emacsframe->output_data.ns)
6756 emacsframe->left_pos = r.origin.x;
6757 emacsframe->top_pos =
6758 [screen frame].size.height - (r.origin.y + r.size.height);
6763 /* Called AFTER method below, but before our windowWillResize call there leads
6764 to windowDidResize -> x_set_window_size. Update emacs' notion of frame
6765 location so set_window_size moves the frame. */
6766 - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
6768 NSTRACE (("[EmacsView windowShouldZoom:toFrame:" NSTRACE_FMT_RECT "]"
6769 NSTRACE_FMT_RETURN "YES"),
6770 NSTRACE_ARG_RECT (newFrame));
6772 emacsframe->output_data.ns->zooming = 1;
6777 /* Override to do something slightly nonstandard, but nice. First click on
6778 zoom button will zoom vertically. Second will zoom completely. Third
6779 returns to original. */
6780 - (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
6781 defaultFrame:(NSRect)defaultFrame
6783 // TODO: Rename to "currentFrame" and assign "result" properly in
6785 NSRect result = [sender frame];
6787 NSTRACE (("[EmacsView windowWillUseStandardFrame:defaultFrame:"
6788 NSTRACE_FMT_RECT "]"),
6789 NSTRACE_ARG_RECT (defaultFrame));
6790 NSTRACE_FSTYPE ("fs_state", fs_state);
6791 NSTRACE_FSTYPE ("fs_before_fs", fs_before_fs);
6792 NSTRACE_FSTYPE ("next_maximized", next_maximized);
6793 NSTRACE_RECT ("ns_userRect", ns_userRect);
6794 NSTRACE_RECT ("[sender frame]", [sender frame]);
6796 if (fs_before_fs != -1) /* Entering fullscreen */
6798 NSTRACE_MSG ("Entering fullscreen");
6799 result = defaultFrame;
6803 // Save the window size and position (frame) before the resize.
6804 if (fs_state != FULLSCREEN_MAXIMIZED
6805 && fs_state != FULLSCREEN_WIDTH)
6807 ns_userRect.size.width = result.size.width;
6808 ns_userRect.origin.x = result.origin.x;
6811 if (fs_state != FULLSCREEN_MAXIMIZED
6812 && fs_state != FULLSCREEN_HEIGHT)
6814 ns_userRect.size.height = result.size.height;
6815 ns_userRect.origin.y = result.origin.y;
6818 NSTRACE_RECT ("ns_userRect (2)", ns_userRect);
6820 if (next_maximized == FULLSCREEN_HEIGHT
6821 || (next_maximized == -1
6822 && abs ((int)(defaultFrame.size.height - result.size.height))
6823 > FRAME_LINE_HEIGHT (emacsframe)))
6826 NSTRACE_MSG ("FULLSCREEN_HEIGHT");
6827 maximized_height = result.size.height = defaultFrame.size.height;
6828 maximized_width = -1;
6829 result.origin.y = defaultFrame.origin.y;
6830 if (ns_userRect.size.height != 0)
6832 result.origin.x = ns_userRect.origin.x;
6833 result.size.width = ns_userRect.size.width;
6835 [self setFSValue: FULLSCREEN_HEIGHT];
6836 #ifdef NS_IMPL_COCOA
6837 maximizing_resize = YES;
6840 else if (next_maximized == FULLSCREEN_WIDTH)
6842 NSTRACE_MSG ("FULLSCREEN_WIDTH");
6843 maximized_width = result.size.width = defaultFrame.size.width;
6844 maximized_height = -1;
6845 result.origin.x = defaultFrame.origin.x;
6846 if (ns_userRect.size.width != 0)
6848 result.origin.y = ns_userRect.origin.y;
6849 result.size.height = ns_userRect.size.height;
6851 [self setFSValue: FULLSCREEN_WIDTH];
6853 else if (next_maximized == FULLSCREEN_MAXIMIZED
6854 || (next_maximized == -1
6855 && abs ((int)(defaultFrame.size.width - result.size.width))
6856 > FRAME_COLUMN_WIDTH (emacsframe)))
6858 NSTRACE_MSG ("FULLSCREEN_MAXIMIZED");
6860 result = defaultFrame; /* second click */
6861 maximized_width = result.size.width;
6862 maximized_height = result.size.height;
6863 [self setFSValue: FULLSCREEN_MAXIMIZED];
6864 #ifdef NS_IMPL_COCOA
6865 maximizing_resize = YES;
6871 NSTRACE_MSG ("Restore");
6872 result = ns_userRect.size.height ? ns_userRect : result;
6873 NSTRACE_RECT ("restore (2)", result);
6874 ns_userRect = NSMakeRect (0, 0, 0, 0);
6875 #ifdef NS_IMPL_COCOA
6876 maximizing_resize = fs_state != FULLSCREEN_NONE;
6878 [self setFSValue: FULLSCREEN_NONE];
6879 maximized_width = maximized_height = -1;
6883 if (fs_before_fs == -1) next_maximized = -1;
6885 NSTRACE_RECT ("Final ns_userRect", ns_userRect);
6886 NSTRACE_MSG ("Final maximized_width: %d", maximized_width);
6887 NSTRACE_MSG ("Final maximized_height: %d", maximized_height);
6888 NSTRACE_FSTYPE ("Final next_maximized", next_maximized);
6890 [self windowWillResize: sender toSize: result.size];
6892 NSTRACE_RETURN_RECT (result);
6898 - (void)windowDidDeminiaturize: sender
6900 NSTRACE ("[EmacsView windowDidDeminiaturize:]");
6901 if (!emacsframe->output_data.ns)
6904 SET_FRAME_ICONIFIED (emacsframe, 0);
6905 SET_FRAME_VISIBLE (emacsframe, 1);
6906 windows_or_buffers_changed = 63;
6910 emacs_event->kind = DEICONIFY_EVENT;
6911 EV_TRAILER ((id)nil);
6916 - (void)windowDidExpose: sender
6918 NSTRACE ("[EmacsView windowDidExpose:]");
6919 if (!emacsframe->output_data.ns)
6922 SET_FRAME_VISIBLE (emacsframe, 1);
6923 SET_FRAME_GARBAGED (emacsframe);
6925 if (send_appdefined)
6926 ns_send_appdefined (-1);
6930 - (void)windowDidMiniaturize: sender
6932 NSTRACE ("[EmacsView windowDidMiniaturize:]");
6933 if (!emacsframe->output_data.ns)
6936 SET_FRAME_ICONIFIED (emacsframe, 1);
6937 SET_FRAME_VISIBLE (emacsframe, 0);
6941 emacs_event->kind = ICONIFY_EVENT;
6942 EV_TRAILER ((id)nil);
6946 #ifdef HAVE_NATIVE_FS
6947 - (NSApplicationPresentationOptions)window:(NSWindow *)window
6948 willUseFullScreenPresentationOptions:
6949 (NSApplicationPresentationOptions)proposedOptions
6951 return proposedOptions|NSApplicationPresentationAutoHideToolbar;
6955 - (void)windowWillEnterFullScreen:(NSNotification *)notification
6957 NSTRACE ("[EmacsView windowWillEnterFullScreen:]");
6958 [self windowWillEnterFullScreen];
6960 - (void)windowWillEnterFullScreen /* provided for direct calls */
6962 NSTRACE ("[EmacsView windowWillEnterFullScreen]");
6963 fs_before_fs = fs_state;
6966 - (void)windowDidEnterFullScreen:(NSNotification *)notification
6968 NSTRACE ("[EmacsView windowDidEnterFullScreen:]");
6969 [self windowDidEnterFullScreen];
6972 - (void)windowDidEnterFullScreen /* provided for direct calls */
6974 NSTRACE ("[EmacsView windowDidEnterFullScreen]");
6975 [self setFSValue: FULLSCREEN_BOTH];
6976 if (! [self fsIsNative])
6978 [self windowDidBecomeKey];
6979 [nonfs_window orderOut:self];
6983 BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (emacsframe) ? YES : NO;
6984 #ifdef NS_IMPL_COCOA
6985 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
6986 unsigned val = (unsigned)[NSApp presentationOptions];
6988 // OSX 10.7 bug fix, the menu won't appear without this.
6989 // val is non-zero on other OSX versions.
6992 NSApplicationPresentationOptions options
6993 = NSApplicationPresentationAutoHideDock
6994 | NSApplicationPresentationAutoHideMenuBar
6995 | NSApplicationPresentationFullScreen
6996 | NSApplicationPresentationAutoHideToolbar;
6998 [NSApp setPresentationOptions: options];
7002 [toolbar setVisible:tbar_visible];
7006 - (void)windowWillExitFullScreen:(NSNotification *)notification
7008 NSTRACE ("[EmacsView windowWillExitFullScreen:]");
7009 [self windowWillExitFullScreen];
7012 - (void)windowWillExitFullScreen /* provided for direct calls */
7014 NSTRACE ("[EmacsView windowWillExitFullScreen]");
7015 if (!FRAME_LIVE_P (emacsframe))
7017 NSTRACE_MSG ("Ignored (frame dead)");
7020 if (next_maximized != -1)
7021 fs_before_fs = next_maximized;
7024 - (void)windowDidExitFullScreen:(NSNotification *)notification
7026 NSTRACE ("[EmacsView windowDidExitFullScreen:]");
7027 [self windowDidExitFullScreen];
7030 - (void)windowDidExitFullScreen /* provided for direct calls */
7032 NSTRACE ("[EmacsView windowDidExitFullScreen]");
7033 if (!FRAME_LIVE_P (emacsframe))
7035 NSTRACE_MSG ("Ignored (frame dead)");
7038 [self setFSValue: fs_before_fs];
7040 #ifdef HAVE_NATIVE_FS
7041 [self updateCollectionBehavior];
7043 if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
7045 [toolbar setVisible:YES];
7046 update_frame_tool_bar (emacsframe);
7047 [self updateFrameSize:YES];
7048 [[self window] display];
7051 [toolbar setVisible:NO];
7053 if (next_maximized != -1)
7054 [[self window] performZoom:self];
7059 return fs_is_native;
7062 - (BOOL)isFullscreen
7064 NSTRACE ("[EmacsView isFullscreen]");
7066 if (! fs_is_native) return nonfs_window != nil;
7067 #ifdef HAVE_NATIVE_FS
7068 return ([[self window] styleMask] & NSFullScreenWindowMask) != 0;
7074 #ifdef HAVE_NATIVE_FS
7075 - (void)updateCollectionBehavior
7077 NSTRACE ("[EmacsView updateCollectionBehavior]");
7079 if (! [self isFullscreen])
7081 NSWindow *win = [self window];
7082 NSWindowCollectionBehavior b = [win collectionBehavior];
7083 if (ns_use_native_fullscreen)
7084 b |= NSWindowCollectionBehaviorFullScreenPrimary;
7086 b &= ~NSWindowCollectionBehaviorFullScreenPrimary;
7088 [win setCollectionBehavior: b];
7089 fs_is_native = ns_use_native_fullscreen;
7094 - (void)toggleFullScreen: (id)sender
7102 NSTRACE ("[EmacsView toggleFullScreen:]");
7106 #ifdef HAVE_NATIVE_FS
7107 [[self window] toggleFullScreen:sender];
7113 onFirstScreen = [[w screen] isEqual:[[NSScreen screens] objectAtIndex:0]];
7116 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
7117 (FRAME_DEFAULT_FACE (f)),
7120 if (fs_state != FULLSCREEN_BOTH)
7122 NSScreen *screen = [w screen];
7124 #if defined (NS_IMPL_COCOA) && \
7125 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
7126 /* Hide ghost menu bar on secondary monitor? */
7127 if (! onFirstScreen)
7128 onFirstScreen = [NSScreen screensHaveSeparateSpaces];
7130 /* Hide dock and menubar if we are on the primary screen. */
7133 #ifdef NS_IMPL_COCOA
7134 NSApplicationPresentationOptions options
7135 = NSApplicationPresentationAutoHideDock
7136 | NSApplicationPresentationAutoHideMenuBar;
7138 [NSApp setPresentationOptions: options];
7140 [NSMenu setMenuBarVisible:NO];
7144 fw = [[EmacsFSWindow alloc]
7145 initWithContentRect:[w contentRectForFrameRect:wr]
7146 styleMask:NSBorderlessWindowMask
7147 backing:NSBackingStoreBuffered
7151 [fw setContentView:[w contentView]];
7152 [fw setTitle:[w title]];
7153 [fw setDelegate:self];
7154 [fw setAcceptsMouseMovedEvents: YES];
7155 #if !defined (NS_IMPL_COCOA) || \
7156 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
7157 [fw useOptimizedDrawing: YES];
7159 [fw setBackgroundColor: col];
7160 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
7163 f->border_width = 0;
7164 FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
7165 tobar_height = FRAME_TOOLBAR_HEIGHT (f);
7166 FRAME_TOOLBAR_HEIGHT (f) = 0;
7170 [self windowWillEnterFullScreen];
7171 [fw makeKeyAndOrderFront:NSApp];
7172 [fw makeFirstResponder:self];
7174 r = [fw frameRectForContentRect:[screen frame]];
7175 [fw setFrame: r display:YES animate:ns_use_fullscreen_animation];
7176 [self windowDidEnterFullScreen];
7187 #ifdef NS_IMPL_COCOA
7188 [NSApp setPresentationOptions: NSApplicationPresentationDefault];
7190 [NSMenu setMenuBarVisible:YES];
7194 [w setContentView:[fw contentView]];
7195 [w setBackgroundColor: col];
7196 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
7199 f->border_width = bwidth;
7200 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
7201 if (FRAME_EXTERNAL_TOOL_BAR (f))
7202 FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
7204 // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications.
7206 [self windowWillExitFullScreen];
7207 [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
7209 [w makeKeyAndOrderFront:NSApp];
7210 [self windowDidExitFullScreen];
7211 [self updateFrameSize:YES];
7217 NSTRACE ("[EmacsView handleFS]");
7219 if (fs_state != emacsframe->want_fullscreen)
7221 if (fs_state == FULLSCREEN_BOTH)
7223 NSTRACE_MSG ("fs_state == FULLSCREEN_BOTH");
7224 [self toggleFullScreen:self];
7227 switch (emacsframe->want_fullscreen)
7229 case FULLSCREEN_BOTH:
7230 NSTRACE_MSG ("FULLSCREEN_BOTH");
7231 [self toggleFullScreen:self];
7233 case FULLSCREEN_WIDTH:
7234 NSTRACE_MSG ("FULLSCREEN_WIDTH");
7235 next_maximized = FULLSCREEN_WIDTH;
7236 if (fs_state != FULLSCREEN_BOTH)
7237 [[self window] performZoom:self];
7239 case FULLSCREEN_HEIGHT:
7240 NSTRACE_MSG ("FULLSCREEN_HEIGHT");
7241 next_maximized = FULLSCREEN_HEIGHT;
7242 if (fs_state != FULLSCREEN_BOTH)
7243 [[self window] performZoom:self];
7245 case FULLSCREEN_MAXIMIZED:
7246 NSTRACE_MSG ("FULLSCREEN_MAXIMIZED");
7247 next_maximized = FULLSCREEN_MAXIMIZED;
7248 if (fs_state != FULLSCREEN_BOTH)
7249 [[self window] performZoom:self];
7251 case FULLSCREEN_NONE:
7252 NSTRACE_MSG ("FULLSCREEN_NONE");
7253 if (fs_state != FULLSCREEN_BOTH)
7255 next_maximized = FULLSCREEN_NONE;
7256 [[self window] performZoom:self];
7261 emacsframe->want_fullscreen = FULLSCREEN_NONE;
7266 - (void) setFSValue: (int)value
7268 NSTRACE ("[EmacsView setFSValue:" NSTRACE_FMT_FSTYPE "]",
7269 NSTRACE_ARG_FSTYPE(value));
7271 Lisp_Object lval = Qnil;
7274 case FULLSCREEN_BOTH:
7277 case FULLSCREEN_WIDTH:
7280 case FULLSCREEN_HEIGHT:
7283 case FULLSCREEN_MAXIMIZED:
7287 store_frame_param (emacsframe, Qfullscreen, lval);
7291 - (void)mouseEntered: (NSEvent *)theEvent
7293 NSTRACE ("[EmacsView mouseEntered:]");
7295 FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
7296 = EV_TIMESTAMP (theEvent);
7300 - (void)mouseExited: (NSEvent *)theEvent
7302 Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL;
7304 NSTRACE ("[EmacsView mouseExited:]");
7309 FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
7310 = EV_TIMESTAMP (theEvent);
7312 if (emacsframe == hlinfo->mouse_face_mouse_frame)
7314 clear_mouse_face (hlinfo);
7315 hlinfo->mouse_face_mouse_frame = 0;
7322 NSTRACE ("[EmacsView menuDown:]");
7323 if (context_menu_value == -1)
7324 context_menu_value = [sender tag];
7327 NSInteger tag = [sender tag];
7328 find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
7329 emacsframe->menu_bar_vector,
7333 ns_send_appdefined (-1);
7338 - (EmacsToolbar *)toolbar
7344 /* this gets called on toolbar button click */
7345 - toolbarClicked: (id)item
7348 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
7350 NSTRACE ("[EmacsView toolbarClicked:]");
7355 /* send first event (for some reason two needed) */
7356 theEvent = [[self window] currentEvent];
7357 emacs_event->kind = TOOL_BAR_EVENT;
7358 XSETFRAME (emacs_event->arg, emacsframe);
7359 EV_TRAILER (theEvent);
7361 emacs_event->kind = TOOL_BAR_EVENT;
7362 /* XSETINT (emacs_event->code, 0); */
7363 emacs_event->arg = AREF (emacsframe->tool_bar_items,
7364 idx + TOOL_BAR_ITEM_KEY);
7365 emacs_event->modifiers = EV_MODIFIERS (theEvent);
7366 EV_TRAILER (theEvent);
7371 - toggleToolbar: (id)sender
7373 NSTRACE ("[EmacsView toggleToolbar:]");
7378 emacs_event->kind = NS_NONKEY_EVENT;
7379 emacs_event->code = KEY_NS_TOGGLE_TOOLBAR;
7380 EV_TRAILER ((id)nil);
7385 - (void)drawRect: (NSRect)rect
7387 int x = NSMinX (rect), y = NSMinY (rect);
7388 int width = NSWidth (rect), height = NSHeight (rect);
7390 NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]",
7391 NSTRACE_ARG_RECT(rect));
7393 if (!emacsframe || !emacsframe->output_data.ns)
7396 ns_clear_frame_area (emacsframe, x, y, width, height);
7398 expose_frame (emacsframe, x, y, width, height);
7402 drawRect: may be called (at least in OS X 10.5) for invisible
7403 views as well for some reason. Thus, do not infer visibility
7406 emacsframe->async_visible = 1;
7407 emacsframe->async_iconified = 0;
7412 /* NSDraggingDestination protocol methods. Actually this is not really a
7413 protocol, but a category of Object. O well... */
7415 -(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
7417 NSTRACE ("[EmacsView draggingEntered:]");
7418 return NSDragOperationGeneric;
7422 -(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
7428 -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
7433 NSEvent *theEvent = [[self window] currentEvent];
7435 NSDragOperation op = [sender draggingSourceOperationMask];
7438 NSTRACE ("[EmacsView performDragOperation:]");
7443 position = [self convertPoint: [sender draggingLocation] fromView: nil];
7444 x = lrint (position.x); y = lrint (position.y);
7446 pb = [sender draggingPasteboard];
7447 type = [pb availableTypeFromArray: ns_drag_types];
7449 if (! (op & (NSDragOperationMove|NSDragOperationDelete)) &&
7450 // URL drags contain all operations (0xf), don't allow all to be set.
7453 if (op & NSDragOperationLink)
7454 modifiers |= NSControlKeyMask;
7455 if (op & NSDragOperationCopy)
7456 modifiers |= NSAlternateKeyMask;
7457 if (op & NSDragOperationGeneric)
7458 modifiers |= NSCommandKeyMask;
7461 modifiers = EV_MODIFIERS2 (modifiers);
7466 else if ([type isEqualToString: NSFilenamesPboardType])
7469 NSEnumerator *fenum;
7472 if (!(files = [pb propertyListForType: type]))
7475 fenum = [files objectEnumerator];
7476 while ( (file = [fenum nextObject]) )
7478 emacs_event->kind = DRAG_N_DROP_EVENT;
7479 XSETINT (emacs_event->x, x);
7480 XSETINT (emacs_event->y, y);
7481 ns_input_file = append2 (ns_input_file,
7482 build_string ([file UTF8String]));
7483 emacs_event->modifiers = modifiers;
7484 emacs_event->arg = list2 (Qfile, build_string ([file UTF8String]));
7485 EV_TRAILER (theEvent);
7489 else if ([type isEqualToString: NSURLPboardType])
7491 NSURL *url = [NSURL URLFromPasteboard: pb];
7492 if (url == nil) return NO;
7494 emacs_event->kind = DRAG_N_DROP_EVENT;
7495 XSETINT (emacs_event->x, x);
7496 XSETINT (emacs_event->y, y);
7497 emacs_event->modifiers = modifiers;
7498 emacs_event->arg = list2 (Qurl,
7499 build_string ([[url absoluteString]
7501 EV_TRAILER (theEvent);
7503 if ([url isFileURL] != NO)
7505 NSString *file = [url path];
7506 ns_input_file = append2 (ns_input_file,
7507 build_string ([file UTF8String]));
7511 else if ([type isEqualToString: NSStringPboardType]
7512 || [type isEqualToString: NSTabularTextPboardType])
7516 if (! (data = [pb stringForType: type]))
7519 emacs_event->kind = DRAG_N_DROP_EVENT;
7520 XSETINT (emacs_event->x, x);
7521 XSETINT (emacs_event->y, y);
7522 emacs_event->modifiers = modifiers;
7523 emacs_event->arg = list2 (Qnil, build_string ([data UTF8String]));
7524 EV_TRAILER (theEvent);
7529 fprintf (stderr, "Invalid data type in dragging pasteboard");
7535 - (id) validRequestorForSendType: (NSString *)typeSent
7536 returnType: (NSString *)typeReturned
7538 NSTRACE ("[EmacsView validRequestorForSendType:returnType:]");
7539 if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound
7540 && typeReturned == nil)
7542 if (! NILP (ns_get_local_selection (QPRIMARY, QUTF8_STRING)))
7546 return [super validRequestorForSendType: typeSent
7547 returnType: typeReturned];
7551 /* The next two methods are part of NSServicesRequests informal protocol,
7552 supposedly called when a services menu item is chosen from this app.
7553 But this should not happen because we override the services menu with our
7554 own entries which call ns-perform-service.
7555 Nonetheless, it appeared to happen (under strange circumstances): bug#1435.
7556 So let's at least stub them out until further investigation can be done. */
7558 - (BOOL) readSelectionFromPasteboard: (NSPasteboard *)pb
7560 /* we could call ns_string_from_pasteboard(pboard) here but then it should
7561 be written into the buffer in place of the existing selection..
7562 ordinary service calls go through functions defined in ns-win.el */
7566 - (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types
7568 NSArray *typesDeclared;
7571 NSTRACE ("[EmacsView writeSelectionToPasteboard:types:]");
7573 /* We only support NSStringPboardType */
7574 if ([types containsObject:NSStringPboardType] == NO) {
7578 val = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
7579 if (CONSP (val) && SYMBOLP (XCAR (val)))
7582 if (CONSP (val) && NILP (XCDR (val)))
7585 if (! STRINGP (val))
7588 typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
7589 [pb declareTypes:typesDeclared owner:nil];
7590 ns_string_to_pasteboard (pb, val);
7595 /* setMini =YES means set from internal (gives a finder icon), NO means set nil
7596 (gives a miniaturized version of the window); currently we use the latter for
7597 frames whose active buffer doesn't correspond to any file
7598 (e.g., '*scratch*') */
7599 - setMiniwindowImage: (BOOL) setMini
7601 id image = [[self window] miniwindowImage];
7602 NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini);
7604 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
7605 about "AppleDockIconEnabled" notwithstanding, however the set message
7606 below has its effect nonetheless. */
7607 if (image != emacsframe->output_data.ns->miniimage)
7609 if (image && [image isKindOfClass: [EmacsImage class]])
7611 [[self window] setMiniwindowImage:
7612 setMini ? emacsframe->output_data.ns->miniimage : nil];
7619 - (void) setRows: (int) r andColumns: (int) c
7621 NSTRACE ("[EmacsView setRows:%d andColumns:%d]", r, c);
7626 - (int) fullscreenState
7631 @end /* EmacsView */
7635 /* ==========================================================================
7637 EmacsWindow implementation
7639 ========================================================================== */
7641 @implementation EmacsWindow
7643 #ifdef NS_IMPL_COCOA
7644 - (id)accessibilityAttributeValue:(NSString *)attribute
7646 Lisp_Object str = Qnil;
7647 struct frame *f = SELECTED_FRAME ();
7648 struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contents);
7650 NSTRACE ("[EmacsWindow accessibilityAttributeValue:]");
7652 if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
7653 return NSAccessibilityTextFieldRole;
7655 if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]
7656 && curbuf && ! NILP (BVAR (curbuf, mark_active)))
7658 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
7660 else if (curbuf && [attribute isEqualToString:NSAccessibilityValueAttribute])
7662 if (! NILP (BVAR (curbuf, mark_active)))
7663 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
7667 ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf);
7668 ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte;
7669 ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf);
7671 if (! NILP (BVAR (curbuf, enable_multibyte_characters)))
7672 str = make_uninit_multibyte_string (range, byte_range);
7674 str = make_uninit_string (range);
7675 /* To check: This returns emacs-utf-8, which is a superset of utf-8.
7676 Is this a problem? */
7677 memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range);
7684 if (CONSP (str) && SYMBOLP (XCAR (str)))
7687 if (CONSP (str) && NILP (XCDR (str)))
7692 const char *utfStr = SSDATA (str);
7693 NSString *nsStr = [NSString stringWithUTF8String: utfStr];
7698 return [super accessibilityAttributeValue:attribute];
7700 #endif /* NS_IMPL_COCOA */
7702 /* Constrain size and placement of a frame.
7704 By returning the original "frameRect", the frame is not
7705 constrained. This can lead to unwanted situations where, for
7706 example, the menu bar covers the frame.
7708 The default implementation (accessed using "super") constrains the
7709 frame to the visible area of SCREEN, minus the menu bar (if
7710 present) and the Dock. Note that default implementation also calls
7711 windowWillResize, with the frame it thinks should have. (This can
7712 make the frame exit maximized mode.)
7714 Note that this should work in situations where multiple monitors
7715 are present. Common configurations are side-by-side monitors and a
7716 monitor on top of another (e.g. when a laptop is placed under a
7718 - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
7720 NSTRACE ("[EmacsWindow constrainFrameRect:" NSTRACE_FMT_RECT " toScreen:]",
7721 NSTRACE_ARG_RECT (frameRect));
7723 #ifdef NS_IMPL_COCOA
7724 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
7725 // If separate spaces is on, it is like each screen is independent. There is
7726 // no spanning of frames across screens.
7727 if ([NSScreen screensHaveSeparateSpaces])
7729 NSTRACE_MSG ("Screens have separate spaces");
7730 frameRect = [super constrainFrameRect:frameRect toScreen:screen];
7731 NSTRACE_RETURN_RECT (frameRect);
7737 return constrain_frame_rect(frameRect);
7741 - (void)performZoom:(id)sender
7743 NSTRACE ("[EmacsWindow performZoom:]");
7745 return [super performZoom:sender];
7748 - (void)zoom:(id)sender
7750 struct frame * f = SELECTED_FRAME ();
7752 NSTRACE ("[EmacsWindow zoom:]");
7754 ns_update_auto_hide_menu_bar();
7756 // Below are three zoom implementations. In the final commit, the
7757 // idea is that the last should be included.
7760 // Native zoom done using the standard zoom animation. Size of the
7761 // resulting frame reduced to accommodate the Dock and, if present,
7763 [super zoom:sender];
7766 // Native zoom done using the standard zoom animation, plus an
7767 // explicit resize to cover the full screen.
7768 [super zoom:sender];
7770 // After the native zoom, resize the resulting frame to fill the
7771 // entire screen, except the menu-bar.
7773 // This works for all practical purposes. (The only minor oddity is
7774 // when transiting from full-height frame to a maximized, the
7775 // animation reduces the height of the frame slightly (to the 4
7776 // pixels needed to accommodate the Doc) before it snaps back into
7777 // full height. The user would need a very trained eye to spot
7779 NSScreen * screen = [self screen];
7782 int fs_state = [(EmacsView *)[self delegate] fullscreenState];
7784 NSTRACE_FSTYPE ("fullscreenState", fs_state);
7786 NSRect sr = [screen frame];
7787 NSRect wr = [self frame];
7788 NSTRACE_RECT ("Rect after zoom", wr);
7792 if (fs_state == FULLSCREEN_MAXIMIZED
7793 || fs_state == FULLSCREEN_HEIGHT)
7796 newWr.size.height = sr.size.height - ns_menu_bar_height(screen);
7799 if (fs_state == FULLSCREEN_MAXIMIZED
7800 || fs_state == FULLSCREEN_WIDTH)
7803 newWr.size.width = sr.size.width;
7806 if (newWr.size.width != wr.size.width
7807 || newWr.size.height != wr.size.height
7808 || newWr.origin.x != wr.origin.x
7809 || newWr.origin.y != wr.origin.y)
7811 NSTRACE_MSG ("New frame different");
7812 [self setFrame: newWr display: NO];
7816 // Non-native zoom which is done instantaneously. The resulting frame
7817 // covers the entire screen, except the menu-bar, if present.
7818 NSScreen * screen = [self screen];
7821 NSRect sr = [screen frame];
7822 sr.size.height -= ns_menu_bar_height (screen);
7824 sr = [[self delegate] windowWillUseStandardFrame:self
7826 [self setFrame: sr display: NO];
7831 - (void)setFrame:(NSRect)windowFrame
7832 display:(BOOL)displayViews
7834 NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT " display:%d]",
7835 NSTRACE_ARG_RECT (windowFrame), displayViews);
7837 [super setFrame:windowFrame display:displayViews];
7840 - (void)setFrame:(NSRect)windowFrame
7841 display:(BOOL)displayViews
7842 animate:(BOOL)performAnimation
7844 NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT
7845 " display:%d performAnimation:%d]",
7846 NSTRACE_ARG_RECT (windowFrame), displayViews, performAnimation);
7848 [super setFrame:windowFrame display:displayViews animate:performAnimation];
7851 - (void)setFrameTopLeftPoint:(NSPoint)point
7853 NSTRACE ("[EmacsWindow setFrameTopLeftPoint:" NSTRACE_FMT_POINT "]",
7854 NSTRACE_ARG_POINT (point));
7856 [super setFrameTopLeftPoint:point];
7858 @end /* EmacsWindow */
7861 @implementation EmacsFSWindow
7863 - (BOOL)canBecomeKeyWindow
7868 - (BOOL)canBecomeMainWindow
7875 /* ==========================================================================
7877 EmacsScroller implementation
7879 ========================================================================== */
7882 @implementation EmacsScroller
7884 /* for repeat button push */
7885 #define SCROLL_BAR_FIRST_DELAY 0.5
7886 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
7888 + (CGFloat) scrollerWidth
7890 /* TODO: if we want to allow variable widths, this is the place to do it,
7891 however neither GNUstep nor Cocoa support it very well */
7893 #if !defined (NS_IMPL_COCOA) || \
7894 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
7895 r = [NSScroller scrollerWidth];
7897 r = [NSScroller scrollerWidthForControlSize: NSRegularControlSize
7898 scrollerStyle: NSScrollerStyleLegacy];
7904 - initFrame: (NSRect )r window: (Lisp_Object)nwin
7906 NSTRACE ("[EmacsScroller initFrame: window:]");
7908 r.size.width = [EmacsScroller scrollerWidth];
7909 [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
7910 [self setContinuous: YES];
7911 [self setEnabled: YES];
7913 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
7914 locked against the top and bottom edges, and right edge on OS X, where
7915 scrollers are on right. */
7916 #ifdef NS_IMPL_GNUSTEP
7917 [self setAutoresizingMask: NSViewMaxXMargin | NSViewHeightSizable];
7919 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
7922 window = XWINDOW (nwin);
7924 pixel_height = NSHeight (r);
7925 if (pixel_height == 0) pixel_height = 1;
7926 min_portion = 20 / pixel_height;
7928 frame = XFRAME (window->frame);
7929 if (FRAME_LIVE_P (frame))
7932 EmacsView *view = FRAME_NS_VIEW (frame);
7933 NSView *sview = [[view window] contentView];
7934 NSArray *subs = [sview subviews];
7936 /* disable optimization stopping redraw of other scrollbars */
7937 view->scrollbarsNeedingUpdate = 0;
7938 for (i =[subs count]-1; i >= 0; i--)
7939 if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]])
7940 view->scrollbarsNeedingUpdate++;
7941 [sview addSubview: self];
7944 /* [self setFrame: r]; */
7950 - (void)setFrame: (NSRect)newRect
7952 NSTRACE ("[EmacsScroller setFrame:]");
7954 /* block_input (); */
7955 pixel_height = NSHeight (newRect);
7956 if (pixel_height == 0) pixel_height = 1;
7957 min_portion = 20 / pixel_height;
7958 [super setFrame: newRect];
7959 /* unblock_input (); */
7965 NSTRACE ("[EmacsScroller dealloc]");
7967 wset_vertical_scroll_bar (window, Qnil);
7975 NSTRACE ("[EmacsScroller condemn]");
7983 NSTRACE ("[EmacsScroller reprieve]");
7991 NSTRACE ("[EmacsScroller judge]");
7992 bool ret = condemned;
7997 /* ensure other scrollbar updates after deletion */
7998 view = (EmacsView *)FRAME_NS_VIEW (frame);
8000 view->scrollbarsNeedingUpdate++;
8002 wset_vertical_scroll_bar (window, Qnil);
8004 [self removeFromSuperview];
8012 - (void)resetCursorRects
8014 NSRect visible = [self visibleRect];
8015 NSTRACE ("[EmacsScroller resetCursorRects]");
8017 if (!NSIsEmptyRect (visible))
8018 [self addCursorRect: visible cursor: [NSCursor arrowCursor]];
8019 [[NSCursor arrowCursor] setOnMouseEntered: YES];
8023 - (int) checkSamePosition: (int) position portion: (int) portion
8026 return em_position ==position && em_portion ==portion && em_whole ==whole
8027 && portion != whole; /* needed for resize empty buf */
8031 - setPosition: (int)position portion: (int)portion whole: (int)whole
8033 NSTRACE ("[EmacsScroller setPosition:portion:whole:]");
8035 em_position = position;
8036 em_portion = portion;
8039 if (portion >= whole)
8041 #ifdef NS_IMPL_COCOA
8042 [self setKnobProportion: 1.0];
8043 [self setDoubleValue: 1.0];
8045 [self setFloatValue: 0.0 knobProportion: 1.0];
8052 portion = max ((float)whole*min_portion/pixel_height, portion);
8053 pos = (float)position / (whole - portion);
8054 por = (CGFloat)portion/whole;
8055 #ifdef NS_IMPL_COCOA
8056 [self setKnobProportion: por];
8057 [self setDoubleValue: pos];
8059 [self setFloatValue: pos knobProportion: por];
8066 /* set up emacs_event */
8067 - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
8071 NSTRACE ("[EmacsScroller sendScrollEventAtLoc:fromEvent:]");
8076 emacs_event->part = last_hit_part;
8077 emacs_event->code = 0;
8078 emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier;
8079 XSETWINDOW (win, window);
8080 emacs_event->frame_or_window = win;
8081 emacs_event->timestamp = EV_TIMESTAMP (e);
8082 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
8083 emacs_event->arg = Qnil;
8084 XSETINT (emacs_event->x, loc * pixel_height);
8085 XSETINT (emacs_event->y, pixel_height-20);
8089 n_emacs_events_pending++;
8090 kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
8093 hold_event (emacs_event);
8094 EVENT_INIT (*emacs_event);
8095 ns_send_appdefined (-1);
8099 /* called manually thru timer to implement repeated button action w/hold-down */
8100 - repeatScroll: (NSTimer *)scrollEntry
8102 NSEvent *e = [[self window] currentEvent];
8103 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
8104 BOOL inKnob = [self testPart: p] == NSScrollerKnob;
8106 NSTRACE ("[EmacsScroller repeatScroll:]");
8108 /* clear timer if need be */
8109 if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
8111 [scroll_repeat_entry invalidate];
8112 [scroll_repeat_entry release];
8113 scroll_repeat_entry = nil;
8119 = [[NSTimer scheduledTimerWithTimeInterval:
8120 SCROLL_BAR_CONTINUOUS_DELAY
8122 selector: @selector (repeatScroll:)
8128 [self sendScrollEventAtLoc: 0 fromEvent: e];
8133 /* Asynchronous mouse tracking for scroller. This allows us to dispatch
8134 mouseDragged events without going into a modal loop. */
8135 - (void)mouseDown: (NSEvent *)e
8138 /* hitPart is only updated AFTER event is passed on */
8139 NSScrollerPart part = [self testPart: [e locationInWindow]];
8140 CGFloat inc = 0.0, loc, kloc, pos;
8143 NSTRACE ("[EmacsScroller mouseDown:]");
8147 case NSScrollerDecrementPage:
8148 last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
8149 case NSScrollerIncrementPage:
8150 last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
8151 case NSScrollerDecrementLine:
8152 last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
8153 case NSScrollerIncrementLine:
8154 last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
8155 case NSScrollerKnob:
8156 last_hit_part = scroll_bar_handle; break;
8157 case NSScrollerKnobSlot: /* GNUstep-only */
8158 last_hit_part = scroll_bar_move_ratio; break;
8159 default: /* NSScrollerNoPart? */
8160 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %ld\n",
8167 pos = 0; /* ignored */
8169 /* set a timer to repeat, as we can't let superclass do this modally */
8171 = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY
8173 selector: @selector (repeatScroll:)
8180 /* handle, or on GNUstep possibly slot */
8181 NSEvent *fake_event;
8183 /* compute float loc in slot and mouse offset on knob */
8184 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
8186 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
8192 else if (loc >= NSHeight (sr))
8194 loc = NSHeight (sr);
8202 kr = [self convertRect: [self rectForPart: NSScrollerKnob]
8204 kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
8206 last_mouse_offset = kloc;
8208 /* if knob, tell emacs a location offset by knob pos
8209 (to indicate top of handle) */
8210 if (part == NSScrollerKnob)
8211 pos = (loc - last_mouse_offset) / NSHeight (sr);
8213 /* else this is a slot click on GNUstep: go straight there */
8214 pos = loc / NSHeight (sr);
8216 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
8217 fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
8218 location: [e locationInWindow]
8219 modifierFlags: [e modifierFlags]
8220 timestamp: [e timestamp]
8221 windowNumber: [e windowNumber]
8222 context: [e context]
8223 eventNumber: [e eventNumber]
8224 clickCount: [e clickCount]
8225 pressure: [e pressure]];
8226 [super mouseUp: fake_event];
8229 if (part != NSScrollerKnob)
8230 [self sendScrollEventAtLoc: pos fromEvent: e];
8234 /* Called as we manually track scroller drags, rather than superclass. */
8235 - (void)mouseDragged: (NSEvent *)e
8240 NSTRACE ("[EmacsScroller mouseDragged:]");
8242 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
8244 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
8250 else if (loc >= NSHeight (sr) + last_mouse_offset)
8252 loc = NSHeight (sr) + last_mouse_offset;
8255 pos = (loc - last_mouse_offset) / NSHeight (sr);
8256 [self sendScrollEventAtLoc: pos fromEvent: e];
8260 - (void)mouseUp: (NSEvent *)e
8262 NSTRACE ("[EmacsScroller mouseUp:]");
8264 if (scroll_repeat_entry)
8266 [scroll_repeat_entry invalidate];
8267 [scroll_repeat_entry release];
8268 scroll_repeat_entry = nil;
8270 last_hit_part = scroll_bar_above_handle;
8274 /* treat scrollwheel events in the bar as though they were in the main window */
8275 - (void) scrollWheel: (NSEvent *)theEvent
8277 NSTRACE ("[EmacsScroller scrollWheel:]");
8279 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
8280 [view mouseDown: theEvent];
8283 @end /* EmacsScroller */
8286 #ifdef NS_IMPL_GNUSTEP
8287 /* Dummy class to get rid of startup warnings. */
8288 @implementation EmacsDocument
8294 /* ==========================================================================
8296 Font-related functions; these used to be in nsfaces.m
8298 ========================================================================== */
8302 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
8304 struct font *font = XFONT_OBJECT (font_object);
8305 EmacsView *view = FRAME_NS_VIEW (f);
8306 int font_ascent, font_descent;
8309 fontset = fontset_from_font (font_object);
8310 FRAME_FONTSET (f) = fontset;
8312 if (FRAME_FONT (f) == font)
8313 /* This font is already set in frame F. There's nothing more to
8317 FRAME_FONT (f) = font;
8319 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
8320 FRAME_COLUMN_WIDTH (f) = font->average_width;
8321 get_font_ascent_descent (font, &font_ascent, &font_descent);
8322 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
8324 /* Compute the scroll bar width in character columns. */
8325 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
8327 int wid = FRAME_COLUMN_WIDTH (f);
8328 FRAME_CONFIG_SCROLL_BAR_COLS (f)
8329 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
8333 int wid = FRAME_COLUMN_WIDTH (f);
8334 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
8337 /* Compute the scroll bar height in character lines. */
8338 if (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0)
8340 int height = FRAME_LINE_HEIGHT (f);
8341 FRAME_CONFIG_SCROLL_BAR_LINES (f)
8342 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
8346 int height = FRAME_LINE_HEIGHT (f);
8347 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
8350 /* Now make the frame display the given font. */
8351 if (FRAME_NS_WINDOW (f) != 0 && ! [view isFullscreen])
8352 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
8353 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
8360 /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
8361 /* Note: ns_font_to_xlfd and ns_fontname_to_xlfd no longer needed, removed
8365 ns_xlfd_to_fontname (const char *xlfd)
8366 /* --------------------------------------------------------------------------
8367 Convert an X font name (XLFD) to an NS font name.
8368 Only family is used.
8369 The string returned is temporarily allocated.
8370 -------------------------------------------------------------------------- */
8372 char *name = xmalloc (180);
8376 if (!strncmp (xlfd, "--", 2))
8377 sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
8379 sscanf (xlfd, "-%*[^-]-%[^-]179-", name);
8381 /* stopgap for malformed XLFD input */
8382 if (strlen (name) == 0)
8383 strcpy (name, "Monaco");
8385 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
8386 also uppercase after '-' or ' ' */
8387 name[0] = c_toupper (name[0]);
8388 for (len =strlen (name), i =0; i<len; i++)
8394 name[i+1] = c_toupper (name[i+1]);
8396 else if (name[i] == '_')
8400 name[i+1] = c_toupper (name[i+1]);
8403 /*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
8404 ret = [[NSString stringWithUTF8String: name] UTF8String];
8411 syms_of_nsterm (void)
8413 NSTRACE ("syms_of_nsterm");
8415 ns_antialias_threshold = 10.0;
8417 /* from 23+ we need to tell emacs what modifiers there are.. */
8418 DEFSYM (Qmodifier_value, "modifier-value");
8419 DEFSYM (Qalt, "alt");
8420 DEFSYM (Qhyper, "hyper");
8421 DEFSYM (Qmeta, "meta");
8422 DEFSYM (Qsuper, "super");
8423 DEFSYM (Qcontrol, "control");
8424 DEFSYM (QUTF8_STRING, "UTF8_STRING");
8426 DEFSYM (Qfile, "file");
8427 DEFSYM (Qurl, "url");
8429 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
8430 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
8431 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
8432 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
8433 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
8435 DEFVAR_LISP ("ns-input-file", ns_input_file,
8436 "The file specified in the last NS event.");
8437 ns_input_file =Qnil;
8439 DEFVAR_LISP ("ns-working-text", ns_working_text,
8440 "String for visualizing working composition sequence.");
8441 ns_working_text =Qnil;
8443 DEFVAR_LISP ("ns-input-font", ns_input_font,
8444 "The font specified in the last NS event.");
8445 ns_input_font =Qnil;
8447 DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize,
8448 "The fontsize specified in the last NS event.");
8449 ns_input_fontsize =Qnil;
8451 DEFVAR_LISP ("ns-input-line", ns_input_line,
8452 "The line specified in the last NS event.");
8453 ns_input_line =Qnil;
8455 DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
8456 "The service name specified in the last NS event.");
8457 ns_input_spi_name =Qnil;
8459 DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg,
8460 "The service argument specified in the last NS event.");
8461 ns_input_spi_arg =Qnil;
8463 DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier,
8464 "This variable describes the behavior of the alternate or option key.\n\
8465 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8466 Set to none means that the alternate / option key is not interpreted by Emacs\n\
8467 at all, allowing it to be used at a lower level for accented character entry.");
8468 ns_alternate_modifier = Qmeta;
8470 DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier,
8471 "This variable describes the behavior of the right alternate or option key.\n\
8472 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8473 Set to left means be the same key as `ns-alternate-modifier'.\n\
8474 Set to none means that the alternate / option key is not interpreted by Emacs\n\
8475 at all, allowing it to be used at a lower level for accented character entry.");
8476 ns_right_alternate_modifier = Qleft;
8478 DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
8479 "This variable describes the behavior of the command key.\n\
8480 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
8481 ns_command_modifier = Qsuper;
8483 DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
8484 "This variable describes the behavior of the right command key.\n\
8485 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8486 Set to left means be the same key as `ns-command-modifier'.\n\
8487 Set to none means that the command / option key is not interpreted by Emacs\n\
8488 at all, allowing it to be used at a lower level for accented character entry.");
8489 ns_right_command_modifier = Qleft;
8491 DEFVAR_LISP ("ns-control-modifier", ns_control_modifier,
8492 "This variable describes the behavior of the control key.\n\
8493 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
8494 ns_control_modifier = Qcontrol;
8496 DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier,
8497 "This variable describes the behavior of the right control key.\n\
8498 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8499 Set to left means be the same key as `ns-control-modifier'.\n\
8500 Set to none means that the control / option key is not interpreted by Emacs\n\
8501 at all, allowing it to be used at a lower level for accented character entry.");
8502 ns_right_control_modifier = Qleft;
8504 DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
8505 "This variable describes the behavior of the function key (on laptops).\n\
8506 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8507 Set to none means that the function key is not interpreted by Emacs at all,\n\
8508 allowing it to be used at a lower level for accented character entry.");
8509 ns_function_modifier = Qnone;
8511 DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
8512 "Non-nil (the default) means to render text antialiased.");
8513 ns_antialias_text = Qt;
8515 DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
8516 "Whether to confirm application quit using dialog.");
8517 ns_confirm_quit = Qnil;
8519 DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
8520 doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
8521 Only works on OSX 10.6 or later. */);
8522 ns_auto_hide_menu_bar = Qnil;
8524 DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen,
8525 doc: /*Non-nil means to use native fullscreen on OSX >= 10.7.
8526 Nil means use fullscreen the old (< 10.7) way. The old way works better with
8527 multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7.
8528 Default is t for OSX >= 10.7, nil otherwise. */);
8529 #ifdef HAVE_NATIVE_FS
8530 ns_use_native_fullscreen = YES;
8532 ns_use_native_fullscreen = NO;
8534 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
8536 DEFVAR_BOOL ("ns-use-fullscreen-animation", ns_use_fullscreen_animation,
8537 doc: /*Non-nil means use animation on non-native fullscreen.
8538 For native fullscreen, this does nothing.
8539 Default is nil. */);
8540 ns_use_fullscreen_animation = NO;
8542 DEFVAR_BOOL ("ns-use-srgb-colorspace", ns_use_srgb_colorspace,
8543 doc: /*Non-nil means to use sRGB colorspace on OSX >= 10.7.
8544 Note that this does not apply to images.
8545 This variable is ignored on OSX < 10.7 and GNUstep. */);
8546 ns_use_srgb_colorspace = YES;
8548 /* TODO: move to common code */
8549 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
8550 doc: /* Which toolkit scroll bars Emacs uses, if any.
8551 A value of nil means Emacs doesn't use toolkit scroll bars.
8552 With the X Window system, the value is a symbol describing the
8553 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
8554 With MS Windows or Nextstep, the value is t. */);
8555 Vx_toolkit_scroll_bars = Qt;
8557 DEFVAR_BOOL ("x-use-underline-position-properties",
8558 x_use_underline_position_properties,
8559 doc: /*Non-nil means make use of UNDERLINE_POSITION font properties.
8560 A value of nil means ignore them. If you encounter fonts with bogus
8561 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
8562 to 4.1, set this to nil. */);
8563 x_use_underline_position_properties = 0;
8565 DEFVAR_BOOL ("x-underline-at-descent-line",
8566 x_underline_at_descent_line,
8567 doc: /* Non-nil means to draw the underline at the same place as the descent line.
8568 A value of nil means to draw the underline according to the value of the
8569 variable `x-use-underline-position-properties', which is usually at the
8570 baseline level. The default value is nil. */);
8571 x_underline_at_descent_line = 0;
8573 /* Tell Emacs about this window system. */
8574 Fprovide (Qns, Qnil);
8576 DEFSYM (Qcocoa, "cocoa");
8577 DEFSYM (Qgnustep, "gnustep");
8579 #ifdef NS_IMPL_COCOA
8580 Fprovide (Qcocoa, Qnil);
8583 Fprovide (Qgnustep, Qnil);