1 /* NeXT/Open/GNUstep / MacOSX communication module. -*- coding: utf-8 -*-
3 Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2016 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;
1155 - (void)show:(NSView *)view;
1160 @implementation EmacsBell
1164 NSTRACE ("[EmacsBell init]");
1165 if ((self = [super init]))
1169 #ifdef NS_IMPL_GNUSTEP
1170 // GNUstep doesn't provide named images. This was reported in
1171 // 2011, see https://savannah.gnu.org/bugs/?33396
1173 // As a drop in replacement, a semitransparent gray square is used.
1174 self.image = [[NSImage alloc] initWithSize:NSMakeSize(32, 32)];
1175 [self.image lockFocus];
1176 [[NSColor colorForEmacsRed:0.5 green:0.5 blue:0.5 alpha:0.5] set];
1177 NSRectFill(NSMakeRect(0, 0, 32, 32));
1178 [self.image unlockFocus];
1180 self.image = [NSImage imageNamed:NSImageNameCaution];
1186 - (void)show:(NSView *)view
1188 NSTRACE ("[EmacsBell show:]");
1189 NSTRACE_MSG ("nestCount: %u", nestCount);
1191 // Show the image, unless it's already shown.
1194 NSRect rect = [view bounds];
1196 pos.x = rect.origin.x + (rect.size.width - self.image.size.width )/2;
1197 pos.y = rect.origin.y + (rect.size.height - self.image.size.height)/2;
1199 [self setFrameOrigin:pos];
1200 [self setFrameSize:self.image.size];
1203 [[[view window] contentView] addSubview:self
1204 positioned:NSWindowAbove
1210 [self performSelector:@selector(hide) withObject:self afterDelay:0.5];
1216 // Note: Trace output from this method isn't shown, reason unknown.
1217 // NSTRACE ("[EmacsBell hide]");
1222 // Remove the image once the last bell became inactive.
1234 [self removeFromSuperview];
1242 static EmacsBell * bell_view = nil;
1245 ns_ring_bell (struct frame *f)
1246 /* --------------------------------------------------------------------------
1248 -------------------------------------------------------------------------- */
1250 NSTRACE ("ns_ring_bell");
1253 struct frame *frame = SELECTED_FRAME ();
1256 if (bell_view == nil)
1258 bell_view = [[EmacsBell alloc] init];
1264 view = FRAME_NS_VIEW (frame);
1267 [bell_view show:view];
1279 static void hide_bell ()
1280 /* --------------------------------------------------------------------------
1281 Ensure the bell is hidden.
1282 -------------------------------------------------------------------------- */
1284 if (bell_view != nil)
1291 /* ==========================================================================
1293 Frame / window manager related functions
1295 ========================================================================== */
1299 ns_raise_frame (struct frame *f)
1300 /* --------------------------------------------------------------------------
1301 Bring window to foreground and make it active
1302 -------------------------------------------------------------------------- */
1306 check_window_system (f);
1307 view = FRAME_NS_VIEW (f);
1309 if (FRAME_VISIBLE_P (f))
1310 [[view window] makeKeyAndOrderFront: NSApp];
1316 ns_lower_frame (struct frame *f)
1317 /* --------------------------------------------------------------------------
1319 -------------------------------------------------------------------------- */
1323 check_window_system (f);
1324 view = FRAME_NS_VIEW (f);
1326 [[view window] orderBack: NSApp];
1332 ns_frame_raise_lower (struct frame *f, bool raise)
1333 /* --------------------------------------------------------------------------
1335 -------------------------------------------------------------------------- */
1337 NSTRACE ("ns_frame_raise_lower");
1347 ns_frame_rehighlight (struct frame *frame)
1348 /* --------------------------------------------------------------------------
1349 External (hook): called on things like window switching within frame
1350 -------------------------------------------------------------------------- */
1352 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
1353 struct frame *old_highlight = dpyinfo->x_highlight_frame;
1355 NSTRACE ("ns_frame_rehighlight");
1356 if (dpyinfo->x_focus_frame)
1358 dpyinfo->x_highlight_frame
1359 = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1360 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1361 : dpyinfo->x_focus_frame);
1362 if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame))
1364 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
1365 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
1369 dpyinfo->x_highlight_frame = 0;
1371 if (dpyinfo->x_highlight_frame &&
1372 dpyinfo->x_highlight_frame != old_highlight)
1376 x_update_cursor (old_highlight, 1);
1377 x_set_frame_alpha (old_highlight);
1379 if (dpyinfo->x_highlight_frame)
1381 x_update_cursor (dpyinfo->x_highlight_frame, 1);
1382 x_set_frame_alpha (dpyinfo->x_highlight_frame);
1389 x_make_frame_visible (struct frame *f)
1390 /* --------------------------------------------------------------------------
1391 External: Show the window (X11 semantics)
1392 -------------------------------------------------------------------------- */
1394 NSTRACE ("x_make_frame_visible");
1395 /* XXX: at some points in past this was not needed, as the only place that
1396 called this (frame.c:Fraise_frame ()) also called raise_lower;
1397 if this ends up the case again, comment this out again. */
1398 if (!FRAME_VISIBLE_P (f))
1400 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1402 SET_FRAME_VISIBLE (f, 1);
1405 /* Making a new frame from a fullscreen frame will make the new frame
1406 fullscreen also. So skip handleFS as this will print an error. */
1407 if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH
1408 && [view isFullscreen])
1411 if (f->want_fullscreen != FULLSCREEN_NONE)
1422 x_make_frame_invisible (struct frame *f)
1423 /* --------------------------------------------------------------------------
1424 External: Hide the window (X11 semantics)
1425 -------------------------------------------------------------------------- */
1428 NSTRACE ("x_make_frame_invisible");
1429 check_window_system (f);
1430 view = FRAME_NS_VIEW (f);
1431 [[view window] orderOut: NSApp];
1432 SET_FRAME_VISIBLE (f, 0);
1433 SET_FRAME_ICONIFIED (f, 0);
1438 x_iconify_frame (struct frame *f)
1439 /* --------------------------------------------------------------------------
1440 External: Iconify window
1441 -------------------------------------------------------------------------- */
1444 struct ns_display_info *dpyinfo;
1446 NSTRACE ("x_iconify_frame");
1447 check_window_system (f);
1448 view = FRAME_NS_VIEW (f);
1449 dpyinfo = FRAME_DISPLAY_INFO (f);
1451 if (dpyinfo->x_highlight_frame == f)
1452 dpyinfo->x_highlight_frame = 0;
1454 if ([[view window] windowNumber] <= 0)
1456 /* the window is still deferred. Make it very small, bring it
1457 on screen and order it out. */
1458 NSRect s = { { 100, 100}, {0, 0} };
1460 t = [[view window] frame];
1461 [[view window] setFrame: s display: NO];
1462 [[view window] orderBack: NSApp];
1463 [[view window] orderOut: NSApp];
1464 [[view window] setFrame: t display: NO];
1466 [[view window] miniaturize: NSApp];
1469 /* Free X resources of frame F. */
1472 x_free_frame_resources (struct frame *f)
1475 struct ns_display_info *dpyinfo;
1476 Mouse_HLInfo *hlinfo;
1478 NSTRACE ("x_free_frame_resources");
1479 check_window_system (f);
1480 view = FRAME_NS_VIEW (f);
1481 dpyinfo = FRAME_DISPLAY_INFO (f);
1482 hlinfo = MOUSE_HL_INFO (f);
1484 [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
1488 free_frame_menubar (f);
1489 free_frame_faces (f);
1491 if (f == dpyinfo->x_focus_frame)
1492 dpyinfo->x_focus_frame = 0;
1493 if (f == dpyinfo->x_highlight_frame)
1494 dpyinfo->x_highlight_frame = 0;
1495 if (f == hlinfo->mouse_face_mouse_frame)
1496 reset_mouse_highlight (hlinfo);
1498 if (f->output_data.ns->miniimage != nil)
1499 [f->output_data.ns->miniimage release];
1501 [[view window] close];
1504 xfree (f->output_data.ns);
1510 x_destroy_window (struct frame *f)
1511 /* --------------------------------------------------------------------------
1512 External: Delete the window
1513 -------------------------------------------------------------------------- */
1515 NSTRACE ("x_destroy_window");
1516 check_window_system (f);
1517 x_free_frame_resources (f);
1523 x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1524 /* --------------------------------------------------------------------------
1525 External: Position the window
1526 -------------------------------------------------------------------------- */
1528 NSView *view = FRAME_NS_VIEW (f);
1529 NSArray *screens = [NSScreen screens];
1530 NSScreen *fscreen = [screens objectAtIndex: 0];
1531 NSScreen *screen = [[view window] screen];
1533 NSTRACE ("x_set_offset");
1540 if (view != nil && screen && fscreen)
1542 f->left_pos = f->size_hint_flags & XNegative
1543 ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
1545 /* We use visibleFrame here to take menu bar into account.
1546 Ideally we should also adjust left/top with visibleFrame.origin. */
1548 f->top_pos = f->size_hint_flags & YNegative
1549 ? ([screen visibleFrame].size.height + f->top_pos
1550 - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
1551 - FRAME_TOOLBAR_HEIGHT (f))
1553 #ifdef NS_IMPL_GNUSTEP
1554 if (f->left_pos < 100)
1555 f->left_pos = 100; /* don't overlap menu */
1557 /* Constrain the setFrameTopLeftPoint so we don't move behind the
1559 NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos),
1560 SCREENMAXBOUND ([fscreen frame].size.height
1562 NSTRACE_POINT ("setFrameTopLeftPoint", pt);
1563 [[view window] setFrameTopLeftPoint: pt];
1564 f->size_hint_flags &= ~(XNegative|YNegative);
1572 x_set_window_size (struct frame *f,
1573 bool change_gravity,
1577 /* --------------------------------------------------------------------------
1578 Adjust window pixel size based on given character grid size
1579 Impl is a bit more complex than other terms, need to do some
1581 -------------------------------------------------------------------------- */
1583 EmacsView *view = FRAME_NS_VIEW (f);
1584 NSWindow *window = [view window];
1585 NSRect wr = [window frame];
1586 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1587 int pixelwidth, pixelheight;
1588 int orig_height = wr.size.height;
1590 NSTRACE ("x_set_window_size");
1595 NSTRACE_RECT ("current", wr);
1596 NSTRACE_MSG ("Width:%d Height:%d Pixelwise:%d", width, height, pixelwise);
1597 NSTRACE_MSG ("Font %d x %d", FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f));
1603 pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
1604 pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
1608 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
1609 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
1612 /* If we have a toolbar, take its height into account. */
1613 if (tb && ! [view isFullscreen])
1615 /* NOTE: previously this would generate wrong result if toolbar not
1616 yet displayed and fixing toolbar_height=32 helped, but
1617 now (200903) seems no longer needed */
1618 FRAME_TOOLBAR_HEIGHT (f) =
1619 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1620 - FRAME_NS_TITLEBAR_HEIGHT (f);
1622 /* Only breaks things here, removed by martin 2015-09-30. */
1623 #ifdef NS_IMPL_GNUSTEP
1624 FRAME_TOOLBAR_HEIGHT (f) -= 3;
1629 FRAME_TOOLBAR_HEIGHT (f) = 0;
1631 wr.size.width = pixelwidth + f->border_width;
1632 wr.size.height = pixelheight;
1633 if (! [view isFullscreen])
1634 wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f)
1635 + FRAME_TOOLBAR_HEIGHT (f);
1637 /* Do not try to constrain to this screen. We may have multiple
1638 screens, and want Emacs to span those. Constraining to screen
1639 prevents that, and that is not nice to the user. */
1640 if (f->output_data.ns->zooming)
1641 f->output_data.ns->zooming = 0;
1643 wr.origin.y += orig_height - wr.size.height;
1645 frame_size_history_add
1646 (f, Qx_set_window_size_1, width, height,
1647 list5 (Fcons (make_number (pixelwidth), make_number (pixelheight)),
1648 Fcons (make_number (wr.size.width), make_number (wr.size.height)),
1649 make_number (f->border_width),
1650 make_number (FRAME_NS_TITLEBAR_HEIGHT (f)),
1651 make_number (FRAME_TOOLBAR_HEIGHT (f))));
1653 [window setFrame: wr display: YES];
1655 /* This is a trick to compensate for Emacs' managing the scrollbar area
1656 as a fixed number of standard character columns. Instead of leaving
1657 blank space for the extra, we chopped it off above. Now for
1658 left-hand scrollbars, we shift all rendering to the left by the
1659 difference between the real width and Emacs' imagined one. For
1660 right-hand bars, don't worry about it since the extra is never used.
1661 (Obviously doesn't work for vertically split windows tho..) */
1663 NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
1664 ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
1665 - NS_SCROLL_BAR_WIDTH (f), 0)
1666 : NSMakePoint (0, 0);
1668 [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
1669 [view setBoundsOrigin: origin];
1672 [view updateFrameSize: NO];
1678 ns_fullscreen_hook (struct frame *f)
1680 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1682 NSTRACE ("ns_fullscreen_hook");
1684 if (!FRAME_VISIBLE_P (f))
1687 if (! [view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH)
1689 /* Old style fs don't initiate correctly if created from
1690 init/default-frame alist, so use a timer (not nice...).
1692 [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view
1693 selector: @selector (handleFS)
1694 userInfo: nil repeats: NO];
1703 /* ==========================================================================
1707 ========================================================================== */
1711 ns_lookup_indexed_color (unsigned long idx, struct frame *f)
1713 struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
1714 if (idx < 1 || idx >= color_table->avail)
1716 return color_table->colors[idx];
1721 ns_index_color (NSColor *color, struct frame *f)
1723 struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
1727 if (!color_table->colors)
1729 color_table->size = NS_COLOR_CAPACITY;
1730 color_table->avail = 1; /* skip idx=0 as marker */
1731 color_table->colors = xmalloc (color_table->size * sizeof (NSColor *));
1732 color_table->colors[0] = nil;
1733 color_table->empty_indices = [[NSMutableSet alloc] init];
1736 /* Do we already have this color? */
1737 for (i = 1; i < color_table->avail; i++)
1738 if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
1741 if ([color_table->empty_indices count] > 0)
1743 NSNumber *index = [color_table->empty_indices anyObject];
1744 [color_table->empty_indices removeObject: index];
1745 idx = [index unsignedLongValue];
1749 if (color_table->avail == color_table->size)
1750 color_table->colors =
1751 xpalloc (color_table->colors, &color_table->size, 1,
1752 min (ULONG_MAX, PTRDIFF_MAX), sizeof *color_table->colors);
1753 idx = color_table->avail++;
1756 color_table->colors[idx] = color;
1758 /*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1764 ns_free_indexed_color (unsigned long idx, struct frame *f)
1766 struct ns_color_table *color_table;
1773 color_table = FRAME_DISPLAY_INFO (f)->color_table;
1775 if (idx <= 0 || idx >= color_table->size) {
1776 message1 ("ns_free_indexed_color: Color index out of range.\n");
1780 index = [NSNumber numberWithUnsignedInt: idx];
1781 if ([color_table->empty_indices containsObject: index]) {
1782 message1 ("ns_free_indexed_color: attempt to free already freed color.\n");
1786 color = color_table->colors[idx];
1788 color_table->colors[idx] = nil;
1789 [color_table->empty_indices addObject: index];
1790 /*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1795 ns_get_color (const char *name, NSColor **col)
1796 /* --------------------------------------------------------------------------
1798 -------------------------------------------------------------------------- */
1799 /* On *Step, we attempt to mimic the X11 platform here, down to installing an
1800 X11 rgb.txt-compatible color list in Emacs.clr (see ns_term_init()).
1801 See: http://thread.gmane.org/gmane.emacs.devel/113050/focus=113272). */
1804 static char hex[20];
1806 float r = -1.0, g, b;
1807 NSString *nsname = [NSString stringWithUTF8String: name];
1809 NSTRACE ("ns_get_color(%s, **)", name);
1813 if ([nsname isEqualToString: @"ns_selection_bg_color"])
1815 #ifdef NS_IMPL_COCOA
1816 NSString *defname = [[NSUserDefaults standardUserDefaults]
1817 stringForKey: @"AppleHighlightColor"];
1822 if ((new = [NSColor selectedTextBackgroundColor]) != nil)
1824 *col = [new colorUsingDefaultColorSpace];
1829 nsname = NS_SELECTION_BG_COLOR_DEFAULT;
1831 name = [nsname UTF8String];
1833 else if ([nsname isEqualToString: @"ns_selection_fg_color"])
1835 /* NOTE: OSX applications normally don't set foreground selection, but
1836 text may be unreadable if we don't.
1838 if ((new = [NSColor selectedTextColor]) != nil)
1840 *col = [new colorUsingDefaultColorSpace];
1845 nsname = NS_SELECTION_FG_COLOR_DEFAULT;
1846 name = [nsname UTF8String];
1849 /* First, check for some sort of numeric specification. */
1852 if (name[0] == '0' || name[0] == '1' || name[0] == '.') /* RGB decimal */
1854 NSScanner *scanner = [NSScanner scannerWithString: nsname];
1855 [scanner scanFloat: &r];
1856 [scanner scanFloat: &g];
1857 [scanner scanFloat: &b];
1859 else if (!strncmp(name, "rgb:", 4)) /* A newer X11 format -- rgb:r/g/b */
1860 scaling = (snprintf (hex, sizeof hex, "%s", name + 4) - 2) / 3;
1861 else if (name[0] == '#') /* An old X11 format; convert to newer */
1863 int len = (strlen(name) - 1);
1864 int start = (len % 3 == 0) ? 1 : len / 4 + 1;
1866 scaling = strlen(name+start) / 3;
1867 for (i = 0; i < 3; i++)
1868 sprintf (hex + i * (scaling + 1), "%.*s/", scaling,
1869 name + start + i * scaling);
1870 hex[3 * (scaling + 1) - 1] = '\0';
1876 float fscale = scaling == 4 ? 65535.0 : (scaling == 2 ? 255.0 : 15.0);
1877 if (sscanf (hex, "%x/%x/%x", &rr, &gg, &bb))
1887 *col = [NSColor colorForEmacsRed: r green: g blue: b alpha: 1.0];
1892 /* Otherwise, color is expected to be from a list */
1894 NSEnumerator *lenum, *cenum;
1898 #ifdef NS_IMPL_GNUSTEP
1899 /* XXX: who is wrong, the requestor or the implementation? */
1900 if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
1902 nsname = @"highlightColor";
1905 lenum = [[NSColorList availableColorLists] objectEnumerator];
1906 while ( (clist = [lenum nextObject]) && new == nil)
1908 cenum = [[clist allKeys] objectEnumerator];
1909 while ( (name = [cenum nextObject]) && new == nil )
1911 if ([name compare: nsname
1912 options: NSCaseInsensitiveSearch] == NSOrderedSame )
1913 new = [clist colorWithKey: name];
1919 *col = [new colorUsingDefaultColorSpace];
1926 ns_lisp_to_color (Lisp_Object color, NSColor **col)
1927 /* --------------------------------------------------------------------------
1928 Convert a Lisp string object to a NS color
1929 -------------------------------------------------------------------------- */
1931 NSTRACE ("ns_lisp_to_color");
1932 if (STRINGP (color))
1933 return ns_get_color (SSDATA (color), col);
1934 else if (SYMBOLP (color))
1935 return ns_get_color (SSDATA (SYMBOL_NAME (color)), col);
1941 ns_color_to_lisp (NSColor *col)
1942 /* --------------------------------------------------------------------------
1943 Convert a color to a lisp string with the RGB equivalent
1944 -------------------------------------------------------------------------- */
1946 EmacsCGFloat red, green, blue, alpha, gray;
1949 NSTRACE ("ns_color_to_lisp");
1952 if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
1954 if ((str =[[col colorNameComponent] UTF8String]))
1957 return build_string ((char *)str);
1960 [[col colorUsingDefaultColorSpace]
1961 getRed: &red green: &green blue: &blue alpha: &alpha];
1962 if (red == green && red == blue)
1964 [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
1965 getWhite: &gray alpha: &alpha];
1966 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1967 lrint (gray * 0xff), lrint (gray * 0xff), lrint (gray * 0xff));
1969 return build_string (buf);
1972 snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
1973 lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
1976 return build_string (buf);
1981 ns_query_color(void *col, XColor *color_def, int setPixel)
1982 /* --------------------------------------------------------------------------
1983 Get ARGB values out of NSColor col and put them into color_def.
1984 If setPixel, set the pixel to a concatenated version.
1985 and set color_def pixel to the resulting index.
1986 -------------------------------------------------------------------------- */
1988 EmacsCGFloat r, g, b, a;
1990 [((NSColor *)col) getRed: &r green: &g blue: &b alpha: &a];
1991 color_def->red = r * 65535;
1992 color_def->green = g * 65535;
1993 color_def->blue = b * 65535;
1995 if (setPixel == YES)
1997 = ARGB_TO_ULONG((int)(a*255),
1998 (int)(r*255), (int)(g*255), (int)(b*255));
2003 ns_defined_color (struct frame *f,
2008 /* --------------------------------------------------------------------------
2009 Return true if named color found, and set color_def rgb accordingly.
2010 If makeIndex and alloc are nonzero put the color in the color_table,
2011 and set color_def pixel to the resulting index.
2012 If makeIndex is zero, set color_def pixel to ARGB.
2013 Return false if not found
2014 -------------------------------------------------------------------------- */
2017 NSTRACE_WHEN (NSTRACE_GROUP_COLOR, "ns_defined_color");
2020 if (ns_get_color (name, &col) != 0) /* Color not found */
2025 if (makeIndex && alloc)
2026 color_def->pixel = ns_index_color (col, f);
2027 ns_query_color (col, color_def, !makeIndex);
2034 x_set_frame_alpha (struct frame *f)
2035 /* --------------------------------------------------------------------------
2036 change the entire-frame transparency
2037 -------------------------------------------------------------------------- */
2039 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2041 double alpha_min = 1.0;
2043 NSTRACE ("x_set_frame_alpha");
2045 if (dpyinfo->x_highlight_frame == f)
2046 alpha = f->alpha[0];
2048 alpha = f->alpha[1];
2050 if (FLOATP (Vframe_alpha_lower_limit))
2051 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
2052 else if (INTEGERP (Vframe_alpha_lower_limit))
2053 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
2057 else if (1.0 < alpha)
2059 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
2062 #ifdef NS_IMPL_COCOA
2064 EmacsView *view = FRAME_NS_VIEW (f);
2065 [[view window] setAlphaValue: alpha];
2071 /* ==========================================================================
2075 ========================================================================== */
2079 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
2080 /* --------------------------------------------------------------------------
2081 Programmatically reposition mouse pointer in pixel coordinates
2082 -------------------------------------------------------------------------- */
2084 NSTRACE ("frame_set_mouse_pixel_position");
2087 /* FIXME: this does not work, and what about GNUstep? */
2088 #ifdef NS_IMPL_COCOA
2089 [FRAME_NS_VIEW (f) lockFocus];
2090 PSsetmouse ((float)pix_x, (float)pix_y);
2091 [FRAME_NS_VIEW (f) unlockFocus];
2097 note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y)
2098 /* ------------------------------------------------------------------------
2099 Called by EmacsView on mouseMovement events. Passes on
2100 to emacs mainstream code if we moved off of a rect of interest
2101 known as last_mouse_glyph.
2102 ------------------------------------------------------------------------ */
2104 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2107 // NSTRACE ("note_mouse_movement");
2109 dpyinfo->last_mouse_motion_frame = frame;
2110 r = &dpyinfo->last_mouse_glyph;
2112 /* Note, this doesn't get called for enter/leave, since we don't have a
2113 position. Those are taken care of in the corresponding NSView methods. */
2115 /* has movement gone beyond last rect we were tracking? */
2116 if (x < r->origin.x || x >= r->origin.x + r->size.width
2117 || y < r->origin.y || y >= r->origin.y + r->size.height)
2119 ns_update_begin (frame);
2120 frame->mouse_moved = 1;
2121 note_mouse_highlight (frame, x, y);
2122 remember_mouse_glyph (frame, x, y, r);
2123 ns_update_end (frame);
2132 ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
2133 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
2135 /* --------------------------------------------------------------------------
2136 External (hook): inform emacs about mouse position and hit parts.
2137 If a scrollbar is being dragged, set bar_window, part, x, y, time.
2138 x & y should be position in the scrollbar (the whole bar, not the handle)
2139 and length of scrollbar respectively
2140 -------------------------------------------------------------------------- */
2144 Lisp_Object frame, tail;
2146 struct ns_display_info *dpyinfo;
2148 NSTRACE ("ns_mouse_position");
2152 fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n");
2156 dpyinfo = FRAME_DISPLAY_INFO (*fp);
2160 /* Clear the mouse-moved flag for every frame on this display. */
2161 FOR_EACH_FRAME (tail, frame)
2162 if (FRAME_NS_P (XFRAME (frame))
2163 && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
2164 XFRAME (frame)->mouse_moved = 0;
2166 dpyinfo->last_mouse_scroll_bar = nil;
2167 if (dpyinfo->last_mouse_frame
2168 && FRAME_LIVE_P (dpyinfo->last_mouse_frame))
2169 f = dpyinfo->last_mouse_frame;
2171 f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame : SELECTED_FRAME ();
2173 if (f && FRAME_NS_P (f))
2175 view = FRAME_NS_VIEW (*fp);
2177 position = [[view window] mouseLocationOutsideOfEventStream];
2178 position = [view convertPoint: position fromView: nil];
2179 remember_mouse_glyph (f, position.x, position.y,
2180 &dpyinfo->last_mouse_glyph);
2181 NSTRACE_POINT ("position", position);
2183 if (bar_window) *bar_window = Qnil;
2184 if (part) *part = scroll_bar_above_handle;
2186 if (x) XSETINT (*x, lrint (position.x));
2187 if (y) XSETINT (*y, lrint (position.y));
2189 *time = dpyinfo->last_mouse_movement_time;
2198 ns_frame_up_to_date (struct frame *f)
2199 /* --------------------------------------------------------------------------
2200 External (hook): Fix up mouse highlighting right after a full update.
2201 Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls.
2202 -------------------------------------------------------------------------- */
2204 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_frame_up_to_date");
2208 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2209 if (f == hlinfo->mouse_face_mouse_frame)
2213 note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
2214 hlinfo->mouse_face_mouse_x,
2215 hlinfo->mouse_face_mouse_y);
2224 ns_define_frame_cursor (struct frame *f, Cursor cursor)
2225 /* --------------------------------------------------------------------------
2226 External (RIF): set frame mouse pointer type.
2227 -------------------------------------------------------------------------- */
2229 NSTRACE ("ns_define_frame_cursor");
2230 if (FRAME_POINTER_TYPE (f) != cursor)
2232 EmacsView *view = FRAME_NS_VIEW (f);
2233 FRAME_POINTER_TYPE (f) = cursor;
2234 [[view window] invalidateCursorRectsForView: view];
2235 /* Redisplay assumes this function also draws the changed frame
2236 cursor, but this function doesn't, so do it explicitly. */
2237 x_update_cursor (f, 1);
2243 /* ==========================================================================
2247 ========================================================================== */
2251 ns_convert_key (unsigned code)
2252 /* --------------------------------------------------------------------------
2253 Internal call used by NSView-keyDown.
2254 -------------------------------------------------------------------------- */
2256 const unsigned last_keysym = ARRAYELTS (convert_ns_to_X_keysym);
2258 /* An array would be faster, but less easy to read. */
2259 for (keysym = 0; keysym < last_keysym; keysym += 2)
2260 if (code == convert_ns_to_X_keysym[keysym])
2261 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
2263 /* if decide to use keyCode and Carbon table, use this line:
2264 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
2269 x_get_keysym_name (int keysym)
2270 /* --------------------------------------------------------------------------
2271 Called by keyboard.c. Not sure if the return val is important, except
2273 -------------------------------------------------------------------------- */
2275 static char value[16];
2276 NSTRACE ("x_get_keysym_name");
2277 sprintf (value, "%d", keysym);
2283 /* ==========================================================================
2285 Block drawing operations
2287 ========================================================================== */
2291 ns_redraw_scroll_bars (struct frame *f)
2295 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
2296 NSTRACE ("ns_redraw_scroll_bars");
2297 for (i =[subviews count]-1; i >= 0; i--)
2299 view = [subviews objectAtIndex: i];
2300 if (![view isKindOfClass: [EmacsScroller class]]) continue;
2307 ns_clear_frame (struct frame *f)
2308 /* --------------------------------------------------------------------------
2309 External (hook): Erase the entire frame
2310 -------------------------------------------------------------------------- */
2312 NSView *view = FRAME_NS_VIEW (f);
2315 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame");
2317 /* comes on initial frame because we have
2318 after-make-frame-functions = select-frame */
2319 if (!FRAME_DEFAULT_FACE (f))
2322 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2327 ns_focus (f, &r, 1);
2328 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
2332 /* as of 2006/11 or so this is now needed */
2333 ns_redraw_scroll_bars (f);
2339 ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
2340 /* --------------------------------------------------------------------------
2341 External (RIF): Clear section of frame
2342 -------------------------------------------------------------------------- */
2344 NSRect r = NSMakeRect (x, y, width, height);
2345 NSView *view = FRAME_NS_VIEW (f);
2346 struct face *face = FRAME_DEFAULT_FACE (f);
2351 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area");
2353 r = NSIntersectionRect (r, [view frame]);
2354 ns_focus (f, &r, 1);
2355 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
2364 ns_copy_bits (struct frame *f, NSRect src, NSRect dest)
2366 if (FRAME_NS_VIEW (f))
2368 hide_bell(); // Ensure the bell image isn't scrolled.
2370 ns_focus (f, &dest, 1);
2371 [FRAME_NS_VIEW (f) scrollRect: src
2372 by: NSMakeSize (dest.origin.x - src.origin.x,
2373 dest.origin.y - src.origin.y)];
2379 ns_scroll_run (struct window *w, struct run *run)
2380 /* --------------------------------------------------------------------------
2381 External (RIF): Insert or delete n lines at line vpos
2382 -------------------------------------------------------------------------- */
2384 struct frame *f = XFRAME (w->frame);
2385 int x, y, width, height, from_y, to_y, bottom_y;
2387 NSTRACE ("ns_scroll_run");
2389 /* begin copy from other terms */
2390 /* Get frame-relative bounding box of the text display area of W,
2391 without mode lines. Include in this box the left and right
2393 window_box (w, ANY_AREA, &x, &y, &width, &height);
2395 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2396 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2397 bottom_y = y + height;
2401 /* Scrolling up. Make sure we don't copy part of the mode
2402 line at the bottom. */
2403 if (from_y + run->height > bottom_y)
2404 height = bottom_y - from_y;
2406 height = run->height;
2410 /* Scrolling down. Make sure we don't copy over the mode line.
2412 if (to_y + run->height > bottom_y)
2413 height = bottom_y - to_y;
2415 height = run->height;
2417 /* end copy from other terms */
2427 NSRect srcRect = NSMakeRect (x, from_y, width, height);
2428 NSRect dstRect = NSMakeRect (x, to_y, width, height);
2430 ns_copy_bits (f, srcRect , dstRect);
2438 ns_after_update_window_line (struct window *w, struct glyph_row *desired_row)
2439 /* --------------------------------------------------------------------------
2440 External (RIF): preparatory to fringe update after text was updated
2441 -------------------------------------------------------------------------- */
2446 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_after_update_window_line");
2448 /* begin copy from other terms */
2451 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2452 desired_row->redraw_fringe_bitmaps_p = 1;
2454 /* When a window has disappeared, make sure that no rest of
2455 full-width rows stays visible in the internal border. */
2456 if (windows_or_buffers_changed
2457 && desired_row->full_width_p
2458 && (f = XFRAME (w->frame),
2459 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2461 && (height = desired_row->visible_height,
2464 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2467 ns_clear_frame_area (f, 0, y, width, height);
2468 ns_clear_frame_area (f,
2469 FRAME_PIXEL_WIDTH (f) - width,
2477 ns_shift_glyphs_for_insert (struct frame *f,
2478 int x, int y, int width, int height,
2480 /* --------------------------------------------------------------------------
2481 External (RIF): copy an area horizontally, don't worry about clearing src
2482 -------------------------------------------------------------------------- */
2484 NSRect srcRect = NSMakeRect (x, y, width, height);
2485 NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
2487 NSTRACE ("ns_shift_glyphs_for_insert");
2489 ns_copy_bits (f, srcRect, dstRect);
2494 /* ==========================================================================
2496 Character encoding and metrics
2498 ========================================================================== */
2502 ns_compute_glyph_string_overhangs (struct glyph_string *s)
2503 /* --------------------------------------------------------------------------
2504 External (RIF); compute left/right overhang of whole string and set in s
2505 -------------------------------------------------------------------------- */
2507 struct font *font = s->font;
2511 struct font_metrics metrics;
2512 unsigned int codes[2];
2513 codes[0] = *(s->char2b);
2514 codes[1] = *(s->char2b + s->nchars - 1);
2516 font->driver->text_extents (font, codes, 2, &metrics);
2517 s->left_overhang = -metrics.lbearing;
2519 = metrics.rbearing > metrics.width
2520 ? metrics.rbearing - metrics.width : 0;
2524 s->left_overhang = 0;
2525 if (EQ (font->driver->type, Qns))
2526 s->right_overhang = ((struct nsfont_info *)font)->ital ?
2527 FONT_HEIGHT (font) * 0.2 : 0;
2529 s->right_overhang = 0;
2535 /* ==========================================================================
2537 Fringe and cursor drawing
2539 ========================================================================== */
2542 extern int max_used_fringe_bitmap;
2544 ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2545 struct draw_fringe_bitmap_params *p)
2546 /* --------------------------------------------------------------------------
2547 External (RIF); fringe-related
2548 -------------------------------------------------------------------------- */
2550 /* Fringe bitmaps comes in two variants, normal and periodic. A
2551 periodic bitmap is used to create a continuous pattern. Since a
2552 bitmap is rendered one text line at a time, the start offset (dh)
2553 of the bitmap varies. Concretely, this is used for the empty
2556 For a bitmap, "h + dh" is the full height and is always
2557 invariant. For a normal bitmap "dh" is zero.
2559 For example, when the period is three and the full height is 72
2560 the following combinations exists:
2566 struct frame *f = XFRAME (WINDOW_FRAME (w));
2567 struct face *face = p->face;
2568 static EmacsImage **bimgs = NULL;
2569 static int nBimgs = 0;
2571 NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap");
2572 NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d",
2573 p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh);
2575 /* grow bimgs if needed */
2576 if (nBimgs < max_used_fringe_bitmap)
2578 bimgs = xrealloc (bimgs, max_used_fringe_bitmap * sizeof *bimgs);
2579 memset (bimgs + nBimgs, 0,
2580 (max_used_fringe_bitmap - nBimgs) * sizeof *bimgs);
2581 nBimgs = max_used_fringe_bitmap;
2584 /* Must clip because of partially visible lines. */
2585 ns_clip_to_row (w, row, ANY_AREA, YES);
2589 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2591 if (bx >= 0 && nx > 0)
2593 NSRect r = NSMakeRect (bx, by, nx, ny);
2595 [ns_lookup_indexed_color (face->background, f) set];
2602 NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h);
2603 EmacsImage *img = bimgs[p->which - 1];
2607 // Note: For "periodic" images, allocate one EmacsImage for
2608 // the base image, and use it for all dh:s.
2609 unsigned short *bits = p->bits;
2610 int full_height = p->h + p->dh;
2612 unsigned char *cbits = xmalloc (full_height);
2614 for (i = 0; i < full_height; i++)
2616 img = [[EmacsImage alloc] initFromXBM: cbits width: 8
2619 bimgs[p->which - 1] = img;
2623 NSTRACE_RECT ("r", r);
2626 /* Since we composite the bitmap instead of just blitting it, we need
2627 to erase the whole background. */
2628 [ns_lookup_indexed_color(face->background, f) set];
2634 bm_color = ns_lookup_indexed_color(face->foreground, f);
2635 else if (p->overlay_p)
2636 bm_color = ns_lookup_indexed_color(face->background, f);
2638 bm_color = f->output_data.ns->cursor_color;
2639 [img setXBMColor: bm_color];
2642 #ifdef NS_IMPL_COCOA
2643 // Note: For periodic images, the full image height is "h + hd".
2644 // By using the height h, a suitable part of the image is used.
2645 NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
2647 NSTRACE_RECT ("fromRect", fromRect);
2651 operation: NSCompositeSourceOver
2657 NSPoint pt = r.origin;
2659 [img compositeToPoint: pt operation: NSCompositeSourceOver];
2668 ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2669 int x, int y, enum text_cursor_kinds cursor_type,
2670 int cursor_width, bool on_p, bool active_p)
2671 /* --------------------------------------------------------------------------
2672 External call (RIF): draw cursor.
2673 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
2674 -------------------------------------------------------------------------- */
2677 int fx, fy, h, cursor_height;
2678 struct frame *f = WINDOW_XFRAME (w);
2679 struct glyph *phys_cursor_glyph;
2680 struct glyph *cursor_glyph;
2682 NSColor *hollow_color = FRAME_BACKGROUND_COLOR (f);
2684 /* If cursor is out of bounds, don't draw garbage. This can happen
2685 in mini-buffer windows when switching between echo area glyphs
2688 NSTRACE ("ns_draw_window_cursor");
2693 w->phys_cursor_type = cursor_type;
2694 w->phys_cursor_on_p = on_p;
2696 if (cursor_type == NO_CURSOR)
2698 w->phys_cursor_width = 0;
2702 if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
2704 if (glyph_row->exact_window_width_line_p
2705 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
2707 glyph_row->cursor_in_fringe_p = 1;
2708 draw_fringe_bitmap (w, glyph_row, 0);
2713 /* We draw the cursor (with NSRectFill), then draw the glyph on top
2714 (other terminals do it the other way round). We must set
2715 w->phys_cursor_width to the cursor width. For bar cursors, that
2716 is CURSOR_WIDTH; for box cursors, it is the glyph width. */
2717 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
2719 /* The above get_phys_cursor_geometry call set w->phys_cursor_width
2720 to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */
2721 if (cursor_type == BAR_CURSOR)
2723 if (cursor_width < 1)
2724 cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
2725 w->phys_cursor_width = cursor_width;
2727 /* If we have an HBAR, "cursor_width" MAY specify height. */
2728 else if (cursor_type == HBAR_CURSOR)
2730 cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
2731 if (cursor_height > glyph_row->height)
2732 cursor_height = glyph_row->height;
2733 if (h > cursor_height) // Cursor smaller than line height, move down
2734 fy += h - cursor_height;
2738 r.origin.x = fx, r.origin.y = fy;
2740 r.size.width = w->phys_cursor_width;
2742 /* TODO: only needed in rare cases with last-resort font in HELLO..
2743 should we do this more efficiently? */
2744 ns_clip_to_row (w, glyph_row, ANY_AREA, NO); /* do ns_focus(f, &r, 1); if remove */
2747 face = FACE_FROM_ID (f, phys_cursor_glyph->face_id);
2748 if (face && NS_FACE_BACKGROUND (face)
2749 == ns_index_color (FRAME_CURSOR_COLOR (f), f))
2751 [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
2752 hollow_color = FRAME_CURSOR_COLOR (f);
2755 [FRAME_CURSOR_COLOR (f) set];
2757 #ifdef NS_IMPL_COCOA
2758 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
2759 atomic. Cleaner ways of doing this should be investigated.
2760 One way would be to set a global variable DRAWING_CURSOR
2761 when making the call to draw_phys..(), don't focus in that
2762 case, then move the ns_unfocus() here after that call. */
2763 NSDisableScreenUpdates ();
2766 switch (cursor_type)
2768 case DEFAULT_CURSOR:
2771 case FILLED_BOX_CURSOR:
2774 case HOLLOW_BOX_CURSOR:
2777 NSRectFill (NSInsetRect (r, 1, 1));
2778 [FRAME_CURSOR_COLOR (f) set];
2785 /* If the character under cursor is R2L, draw the bar cursor
2786 on the right of its glyph, rather than on the left. */
2787 cursor_glyph = get_phys_cursor_glyph (w);
2788 if ((cursor_glyph->resolved_level & 1) != 0)
2789 s.origin.x += cursor_glyph->pixel_width - s.size.width;
2796 /* draw the character under the cursor */
2797 if (cursor_type != NO_CURSOR)
2798 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2800 #ifdef NS_IMPL_COCOA
2801 NSEnableScreenUpdates ();
2808 ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2809 /* --------------------------------------------------------------------------
2810 External (RIF): Draw a vertical line.
2811 -------------------------------------------------------------------------- */
2813 struct frame *f = XFRAME (WINDOW_FRAME (w));
2815 NSRect r = NSMakeRect (x, y0, 1, y1-y0);
2817 NSTRACE ("ns_draw_vertical_window_border");
2819 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2821 [ns_lookup_indexed_color(face->foreground, f) set];
2823 ns_focus (f, &r, 1);
2830 ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
2831 /* --------------------------------------------------------------------------
2832 External (RIF): Draw a window divider.
2833 -------------------------------------------------------------------------- */
2835 struct frame *f = XFRAME (WINDOW_FRAME (w));
2837 NSRect r = NSMakeRect (x0, y0, x1-x0, y1-y0);
2839 NSTRACE ("ns_draw_window_divider");
2841 face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
2843 [ns_lookup_indexed_color(face->foreground, f) set];
2845 ns_focus (f, &r, 1);
2851 ns_show_hourglass (struct frame *f)
2853 /* TODO: add NSProgressIndicator to all frames. */
2857 ns_hide_hourglass (struct frame *f)
2859 /* TODO: remove NSProgressIndicator from all frames. */
2862 /* ==========================================================================
2864 Glyph drawing operations
2866 ========================================================================== */
2869 ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2870 /* --------------------------------------------------------------------------
2871 Wrapper utility to account for internal border width on full-width lines,
2872 and allow top full-width rows to hit the frame top. nr should be pointer
2873 to two successive NSRects. Number of rects actually used is returned.
2874 -------------------------------------------------------------------------- */
2876 int n = get_glyph_string_clip_rects (s, nr, 2);
2880 /* --------------------------------------------------------------------
2881 Draw a wavy line under glyph string s. The wave fills wave_height
2888 wave_height = 3 | * * * *
2889 --------------------------------------------------------------------- */
2892 ns_draw_underwave (struct glyph_string *s, EmacsCGFloat width, EmacsCGFloat x)
2894 int wave_height = 3, wave_length = 2;
2895 int y, dx, dy, odd, xmax;
2900 dy = wave_height - 1;
2901 y = s->ybase - wave_height + 3;
2904 /* Find and set clipping rectangle */
2905 waveClip = NSMakeRect (x, y, width, wave_height);
2906 [[NSGraphicsContext currentContext] saveGraphicsState];
2907 NSRectClip (waveClip);
2909 /* Draw the waves */
2910 a.x = x - ((int)(x) % dx) + (EmacsCGFloat) 0.5;
2912 odd = (int)(a.x/dx) % 2;
2913 a.y = b.y = y + 0.5;
2922 [NSBezierPath strokeLineFromPoint:a toPoint:b];
2923 a.x = b.x, a.y = b.y;
2924 b.x += dx, b.y = y + 0.5 + odd*dy;
2928 /* Restore previous clipping rectangle(s) */
2929 [[NSGraphicsContext currentContext] restoreGraphicsState];
2935 ns_draw_text_decoration (struct glyph_string *s, struct face *face,
2936 NSColor *defaultCol, CGFloat width, CGFloat x)
2937 /* --------------------------------------------------------------------------
2938 Draw underline, overline, and strike-through on glyph string s.
2939 -------------------------------------------------------------------------- */
2941 if (s->for_overlaps)
2945 if (face->underline_p)
2947 if (s->face->underline_type == FACE_UNDER_WAVE)
2949 if (face->underline_defaulted_p)
2952 [ns_lookup_indexed_color (face->underline_color, s->f) set];
2954 ns_draw_underwave (s, width, x);
2956 else if (s->face->underline_type == FACE_UNDER_LINE)
2960 unsigned long thickness, position;
2962 /* If the prev was underlined, match its appearance. */
2963 if (s->prev && s->prev->face->underline_p
2964 && s->prev->face->underline_type == FACE_UNDER_LINE
2965 && s->prev->underline_thickness > 0)
2967 thickness = s->prev->underline_thickness;
2968 position = s->prev->underline_position;
2973 unsigned long descent;
2976 descent = s->y + s->height - s->ybase;
2978 /* Use underline thickness of font, defaulting to 1. */
2979 thickness = (font && font->underline_thickness > 0)
2980 ? font->underline_thickness : 1;
2982 /* Determine the offset of underlining from the baseline. */
2983 if (x_underline_at_descent_line)
2984 position = descent - thickness;
2985 else if (x_use_underline_position_properties
2986 && font && font->underline_position >= 0)
2987 position = font->underline_position;
2989 position = lround (font->descent / 2);
2991 position = underline_minimum_offset;
2993 position = max (position, underline_minimum_offset);
2995 /* Ensure underlining is not cropped. */
2996 if (descent <= position)
2998 position = descent - 1;
3001 else if (descent < position + thickness)
3005 s->underline_thickness = thickness;
3006 s->underline_position = position;
3008 r = NSMakeRect (x, s->ybase + position, width, thickness);
3010 if (face->underline_defaulted_p)
3013 [ns_lookup_indexed_color (face->underline_color, s->f) set];
3017 /* Do overline. We follow other terms in using a thickness of 1
3018 and ignoring overline_margin. */
3019 if (face->overline_p)
3022 r = NSMakeRect (x, s->y, width, 1);
3024 if (face->overline_color_defaulted_p)
3027 [ns_lookup_indexed_color (face->overline_color, s->f) set];
3031 /* Do strike-through. We follow other terms for thickness and
3032 vertical position.*/
3033 if (face->strike_through_p)
3038 dy = lrint ((s->height - 1) / 2);
3039 r = NSMakeRect (x, s->y + dy, width, 1);
3041 if (face->strike_through_color_defaulted_p)
3044 [ns_lookup_indexed_color (face->strike_through_color, s->f) set];
3050 ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
3051 char left_p, char right_p)
3052 /* --------------------------------------------------------------------------
3053 Draw an unfilled rect inside r, optionally leaving left and/or right open.
3054 Note we can't just use an NSDrawRect command, because of the possibility
3055 of some sides not being drawn, and because the rect will be filled.
3056 -------------------------------------------------------------------------- */
3062 s.size.height = thickness;
3064 s.origin.y += r.size.height - thickness;
3067 s.size.height = r.size.height;
3068 s.origin.y = r.origin.y;
3070 /* left, right (optional) */
3071 s.size.width = thickness;
3076 s.origin.x += r.size.width - thickness;
3083 ns_draw_relief (NSRect r, int thickness, char raised_p,
3084 char top_p, char bottom_p, char left_p, char right_p,
3085 struct glyph_string *s)
3086 /* --------------------------------------------------------------------------
3087 Draw a relief rect inside r, optionally leaving some sides open.
3088 Note we can't just use an NSDrawBezel command, because of the possibility
3089 of some sides not being drawn, and because the rect will be filled.
3090 -------------------------------------------------------------------------- */
3092 static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
3093 NSColor *newBaseCol = nil;
3096 NSTRACE ("ns_draw_relief");
3100 if (s->face->use_box_color_for_shadows_p)
3102 newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f);
3104 /* else if (s->first_glyph->type == IMAGE_GLYPH
3106 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3108 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
3112 newBaseCol = ns_lookup_indexed_color (s->face->background, s->f);
3115 if (newBaseCol == nil)
3116 newBaseCol = [NSColor grayColor];
3118 if (newBaseCol != baseCol) /* TODO: better check */
3121 baseCol = [newBaseCol retain];
3123 lightCol = [[baseCol highlightWithLevel: 0.2] retain];
3125 darkCol = [[baseCol shadowWithLevel: 0.3] retain];
3128 [(raised_p ? lightCol : darkCol) set];
3130 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
3133 sr.size.height = thickness;
3134 if (top_p) NSRectFill (sr);
3137 sr.size.height = r.size.height;
3138 sr.size.width = thickness;
3139 if (left_p) NSRectFill (sr);
3141 [(raised_p ? darkCol : lightCol) set];
3144 sr.size.width = r.size.width;
3145 sr.size.height = thickness;
3146 sr.origin.y += r.size.height - thickness;
3147 if (bottom_p) NSRectFill (sr);
3150 sr.size.height = r.size.height;
3151 sr.origin.y = r.origin.y;
3152 sr.size.width = thickness;
3153 sr.origin.x += r.size.width - thickness;
3154 if (right_p) NSRectFill (sr);
3159 ns_dumpglyphs_box_or_relief (struct glyph_string *s)
3160 /* --------------------------------------------------------------------------
3161 Function modeled after x_draw_glyph_string_box ().
3162 Sets up parameters for drawing.
3163 -------------------------------------------------------------------------- */
3165 int right_x, last_x;
3166 char left_p, right_p;
3167 struct glyph *last_glyph;
3172 if (s->hl == DRAW_MOUSE_FACE)
3174 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3176 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3181 thickness = face->box_line_width;
3183 NSTRACE ("ns_dumpglyphs_box_or_relief");
3185 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3186 ? WINDOW_RIGHT_EDGE_X (s->w)
3187 : window_box_right (s->w, s->area));
3188 last_glyph = (s->cmp || s->img
3189 ? s->first_glyph : s->first_glyph + s->nchars-1);
3191 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
3192 ? last_x - 1 : min (last_x, s->x + s->background_width) - 1));
3194 left_p = (s->first_glyph->left_box_line_p
3195 || (s->hl == DRAW_MOUSE_FACE
3196 && (s->prev == NULL || s->prev->hl != s->hl)));
3197 right_p = (last_glyph->right_box_line_p
3198 || (s->hl == DRAW_MOUSE_FACE
3199 && (s->next == NULL || s->next->hl != s->hl)));
3201 r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
3203 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
3204 if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
3206 ns_draw_box (r, abs (thickness),
3207 ns_lookup_indexed_color (face->box_color, s->f),
3212 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
3213 1, 1, left_p, right_p, s);
3219 ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
3220 /* --------------------------------------------------------------------------
3221 Modeled after x_draw_glyph_string_background, which draws BG in
3222 certain cases. Others are left to the text rendering routine.
3223 -------------------------------------------------------------------------- */
3225 NSTRACE ("ns_maybe_dumpglyphs_background");
3227 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
3229 int box_line_width = max (s->face->box_line_width, 0);
3230 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3231 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
3232 dimensions, since the actual glyphs might be much
3233 smaller. So in that case we always clear the rectangle
3234 with background color. */
3235 || FONT_TOO_HIGH (s->font)
3236 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
3239 if (s->hl == DRAW_MOUSE_FACE)
3241 face = FACE_FROM_ID (s->f,
3242 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3244 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3247 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3249 [(NS_FACE_BACKGROUND (face) != 0
3250 ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
3251 : FRAME_BACKGROUND_COLOR (s->f)) set];
3254 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
3255 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
3258 if (s->hl != DRAW_CURSOR)
3260 NSRect r = NSMakeRect (s->x, s->y + box_line_width,
3261 s->background_width,
3262 s->height-2*box_line_width);
3266 s->background_filled_p = 1;
3273 ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
3274 /* --------------------------------------------------------------------------
3275 Renders an image and associated borders.
3276 -------------------------------------------------------------------------- */
3278 EmacsImage *img = s->img->pixmap;
3279 int box_line_vwidth = max (s->face->box_line_width, 0);
3280 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3281 int bg_x, bg_y, bg_height;
3288 NSTRACE ("ns_dumpglyphs_image");
3290 if (s->face->box != FACE_NO_BOX
3291 && s->first_glyph->left_box_line_p && s->slice.x == 0)
3292 x += abs (s->face->box_line_width);
3295 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
3296 bg_height = s->height;
3297 /* other terms have this, but was causing problems w/tabbar mode */
3298 /* - 2 * box_line_vwidth; */
3300 if (s->slice.x == 0) x += s->img->hmargin;
3301 if (s->slice.y == 0) y += s->img->vmargin;
3303 /* Draw BG: if we need larger area than image itself cleared, do that,
3304 otherwise, since we composite the image under NS (instead of mucking
3305 with its background color), we must clear just the image area. */
3306 if (s->hl == DRAW_MOUSE_FACE)
3308 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3310 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3313 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3315 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set];
3317 if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin
3318 || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width)
3320 br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height);
3321 s->background_filled_p = 1;
3325 br = NSMakeRect (x, y, s->slice.width, s->slice.height);
3330 /* Draw the image.. do we need to draw placeholder if img ==nil? */
3333 #ifdef NS_IMPL_COCOA
3334 NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height);
3335 NSRect ir = NSMakeRect (s->slice.x, s->slice.y,
3336 s->slice.width, s->slice.height);
3339 operation: NSCompositeSourceOver
3344 [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
3345 operation: NSCompositeSourceOver];
3349 if (s->hl == DRAW_CURSOR)
3351 [FRAME_CURSOR_COLOR (s->f) set];
3352 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3353 tdCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3355 /* Currently on NS img->mask is always 0. Since
3356 get_window_cursor_type specifies a hollow box cursor when on
3357 a non-masked image we never reach this clause. But we put it
3358 in in anticipation of better support for image masks on
3360 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3364 tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3367 /* Draw underline, overline, strike-through. */
3368 ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x);
3370 /* Draw relief, if requested */
3371 if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
3373 if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
3375 th = tool_bar_button_relief >= 0 ?
3376 tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3377 raised_p = (s->hl == DRAW_IMAGE_RAISED);
3381 th = abs (s->img->relief);
3382 raised_p = (s->img->relief > 0);
3385 r.origin.x = x - th;
3386 r.origin.y = y - th;
3387 r.size.width = s->slice.width + 2*th-1;
3388 r.size.height = s->slice.height + 2*th-1;
3389 ns_draw_relief (r, th, raised_p,
3391 s->slice.y + s->slice.height == s->img->height,
3393 s->slice.x + s->slice.width == s->img->width, s);
3396 /* If there is no mask, the background won't be seen,
3397 so draw a rectangle on the image for the cursor.
3398 Do this for all images, getting transparency right is not reliable. */
3399 if (s->hl == DRAW_CURSOR)
3401 int thickness = abs (s->img->relief);
3402 if (thickness == 0) thickness = 1;
3403 ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
3409 ns_dumpglyphs_stretch (struct glyph_string *s)
3414 NSColor *fgCol, *bgCol;
3416 if (!s->background_filled_p)
3418 n = ns_get_glyph_string_clip_rect (s, r);
3419 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
3421 ns_focus (s->f, r, n);
3423 if (s->hl == DRAW_MOUSE_FACE)
3425 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3427 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3430 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3432 bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3433 fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3435 for (i = 0; i < n; ++i)
3437 if (!s->row->full_width_p)
3439 int overrun, leftoverrun;
3441 /* truncate to avoid overwriting fringe and/or scrollbar */
3442 overrun = max (0, (s->x + s->background_width)
3443 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
3444 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
3445 r[i].size.width -= overrun;
3447 /* truncate to avoid overwriting to left of the window box */
3448 leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
3449 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
3451 if (leftoverrun > 0)
3453 r[i].origin.x += leftoverrun;
3454 r[i].size.width -= leftoverrun;
3457 /* XXX: Try to work between problem where a stretch glyph on
3458 a partially-visible bottom row will clear part of the
3459 modeline, and another where list-buffers headers and similar
3460 rows erroneously have visible_height set to 0. Not sure
3461 where this is coming from as other terms seem not to show. */
3462 r[i].size.height = min (s->height, s->row->visible_height);
3467 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
3468 overwriting cursor (usually when cursor on a tab) */
3469 if (s->hl == DRAW_CURSOR)
3474 width = s->w->phys_cursor_width;
3475 r[i].size.width -= width;
3476 r[i].origin.x += width;
3480 /* Draw overlining, etc. on the cursor. */
3481 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3482 ns_draw_text_decoration (s, face, bgCol, width, x);
3484 ns_draw_text_decoration (s, face, fgCol, width, x);
3491 /* Draw overlining, etc. on the stretch glyph (or the part
3492 of the stretch glyph after the cursor). */
3493 ns_draw_text_decoration (s, face, fgCol, r[i].size.width,
3497 s->background_filled_p = 1;
3503 ns_draw_composite_glyph_string_foreground (struct glyph_string *s)
3506 struct font *font = s->font;
3508 /* If first glyph of S has a left box line, start drawing the text
3509 of S to the right of that box line. */
3510 if (s->face && s->face->box != FACE_NO_BOX
3511 && s->first_glyph->left_box_line_p)
3512 x = s->x + eabs (s->face->box_line_width);
3516 /* S is a glyph string for a composition. S->cmp_from is the index
3517 of the first character drawn for glyphs of this composition.
3518 S->cmp_from == 0 means we are drawing the very first character of
3519 this composition. */
3521 /* Draw a rectangle for the composition if the font for the very
3522 first character of the composition could not be loaded. */
3523 if (s->font_not_found_p)
3525 if (s->cmp_from == 0)
3527 NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1);
3528 ns_draw_box (r, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
3531 else if (! s->first_glyph->u.cmp.automatic)
3535 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
3536 /* TAB in a composition means display glyphs with padding
3537 space on the left or right. */
3538 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
3540 int xx = x + s->cmp->offsets[j * 2];
3541 int yy = y - s->cmp->offsets[j * 2 + 1];
3543 font->driver->draw (s, j, j + 1, xx, yy, false);
3544 if (s->face->overstrike)
3545 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
3550 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
3555 for (i = j = s->cmp_from; i < s->cmp_to; i++)
3557 glyph = LGSTRING_GLYPH (gstring, i);
3558 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
3559 width += LGLYPH_WIDTH (glyph);
3562 int xoff, yoff, wadjust;
3566 font->driver->draw (s, j, i, x, y, false);
3567 if (s->face->overstrike)
3568 font->driver->draw (s, j, i, x + 1, y, false);
3571 xoff = LGLYPH_XOFF (glyph);
3572 yoff = LGLYPH_YOFF (glyph);
3573 wadjust = LGLYPH_WADJUST (glyph);
3574 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
3575 if (s->face->overstrike)
3576 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
3585 font->driver->draw (s, j, i, x, y, false);
3586 if (s->face->overstrike)
3587 font->driver->draw (s, j, i, x + 1, y, false);
3593 ns_draw_glyph_string (struct glyph_string *s)
3594 /* --------------------------------------------------------------------------
3595 External (RIF): Main draw-text call.
3596 -------------------------------------------------------------------------- */
3598 /* TODO (optimize): focus for box and contents draw */
3601 char box_drawn_p = 0;
3602 struct font *font = s->face->font;
3603 if (! font) font = FRAME_FONT (s->f);
3605 NSTRACE_WHEN (NSTRACE_GROUP_GLYPHS, "ns_draw_glyph_string");
3607 if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
3610 struct glyph_string *next;
3612 for (width = 0, next = s->next;
3613 next && width < s->right_overhang;
3614 width += next->width, next = next->next)
3615 if (next->first_glyph->type != IMAGE_GLYPH)
3617 if (next->first_glyph->type != STRETCH_GLYPH)
3619 n = ns_get_glyph_string_clip_rect (s->next, r);
3620 ns_focus (s->f, r, n);
3621 ns_maybe_dumpglyphs_background (s->next, 1);
3626 ns_dumpglyphs_stretch (s->next);
3628 next->num_clips = 0;
3632 if (!s->for_overlaps && s->face->box != FACE_NO_BOX
3633 && (s->first_glyph->type == CHAR_GLYPH
3634 || s->first_glyph->type == COMPOSITE_GLYPH))
3636 n = ns_get_glyph_string_clip_rect (s, r);
3637 ns_focus (s->f, r, n);
3638 ns_maybe_dumpglyphs_background (s, 1);
3639 ns_dumpglyphs_box_or_relief (s);
3644 switch (s->first_glyph->type)
3648 n = ns_get_glyph_string_clip_rect (s, r);
3649 ns_focus (s->f, r, n);
3650 ns_dumpglyphs_image (s, r[0]);
3655 ns_dumpglyphs_stretch (s);
3659 case COMPOSITE_GLYPH:
3660 n = ns_get_glyph_string_clip_rect (s, r);
3661 ns_focus (s->f, r, n);
3663 if (s->for_overlaps || (s->cmp_from > 0
3664 && ! s->first_glyph->u.cmp.automatic))
3665 s->background_filled_p = 1;
3667 ns_maybe_dumpglyphs_background
3668 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3670 flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
3671 (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
3672 (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
3673 NS_DUMPGLYPH_NORMAL));
3675 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3677 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3678 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3679 NS_FACE_FOREGROUND (s->face) = tmp;
3683 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
3686 ns_draw_composite_glyph_string_foreground (s);
3689 (s, s->cmp_from, s->nchars, s->x, s->ybase,
3690 (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
3691 || flags == NS_DUMPGLYPH_MOUSEFACE);
3695 NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0
3696 ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face),
3698 : FRAME_FOREGROUND_COLOR (s->f));
3701 /* Draw underline, overline, strike-through. */
3702 ns_draw_text_decoration (s, s->face, col, s->width, s->x);
3705 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3707 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
3708 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
3709 NS_FACE_FOREGROUND (s->face) = tmp;
3715 case GLYPHLESS_GLYPH:
3716 n = ns_get_glyph_string_clip_rect (s, r);
3717 ns_focus (s->f, r, n);
3719 if (s->for_overlaps || (s->cmp_from > 0
3720 && ! s->first_glyph->u.cmp.automatic))
3721 s->background_filled_p = 1;
3723 ns_maybe_dumpglyphs_background
3724 (s, s->first_glyph->type == COMPOSITE_GLYPH);
3726 /* Not yet implemented. */
3735 /* Draw box if not done already. */
3736 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
3738 n = ns_get_glyph_string_clip_rect (s, r);
3739 ns_focus (s->f, r, n);
3740 ns_dumpglyphs_box_or_relief (s);
3749 /* ==========================================================================
3753 ========================================================================== */
3757 ns_send_appdefined (int value)
3758 /* --------------------------------------------------------------------------
3759 Internal: post an appdefined event which EmacsApp-sendEvent will
3760 recognize and take as a command to halt the event loop.
3761 -------------------------------------------------------------------------- */
3763 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_send_appdefined(%d)", value);
3765 #ifdef NS_IMPL_GNUSTEP
3766 // GNUstep needs postEvent to happen on the main thread.
3767 if (! [[NSThread currentThread] isMainThread])
3769 EmacsApp *app = (EmacsApp *)NSApp;
3770 app->nextappdefined = value;
3771 [app performSelectorOnMainThread:@selector (sendFromMainThread:)
3778 /* Only post this event if we haven't already posted one. This will end
3779 the [NXApp run] main loop after having processed all events queued at
3782 #ifdef NS_IMPL_COCOA
3783 if (! send_appdefined)
3785 /* OSX 10.10.1 swallows the AppDefined event we are sending ourselves
3786 in certain situations (rapid incoming events).
3787 So check if we have one, if not add one. */
3788 NSEvent *appev = [NSApp nextEventMatchingMask:NSApplicationDefinedMask
3789 untilDate:[NSDate distantPast]
3790 inMode:NSDefaultRunLoopMode
3792 if (! appev) send_appdefined = YES;
3796 if (send_appdefined)
3800 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
3801 send_appdefined = NO;
3803 /* Don't need wakeup timer any more */
3806 [timed_entry invalidate];
3807 [timed_entry release];
3811 nxev = [NSEvent otherEventWithType: NSApplicationDefined
3812 location: NSMakePoint (0, 0)
3815 windowNumber: [[NSApp mainWindow] windowNumber]
3816 context: [NSApp context]
3821 /* Post an application defined event on the event queue. When this is
3822 received the [NXApp run] will return, thus having processed all
3823 events which are currently queued. */
3824 [NSApp postEvent: nxev atStart: NO];
3828 #ifdef HAVE_NATIVE_FS
3832 Lisp_Object frame, tail;
3834 if (ns_last_use_native_fullscreen == ns_use_native_fullscreen)
3837 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
3839 FOR_EACH_FRAME (tail, frame)
3841 struct frame *f = XFRAME (frame);
3844 EmacsView *view = FRAME_NS_VIEW (f);
3845 [view updateCollectionBehavior];
3851 /* GNUstep does not have cancelTracking. */
3852 #ifdef NS_IMPL_COCOA
3853 /* Check if menu open should be canceled or continued as normal. */
3855 ns_check_menu_open (NSMenu *menu)
3857 /* Click in menu bar? */
3858 NSArray *a = [[NSApp mainMenu] itemArray];
3862 if (menu == nil) // Menu tracking ended.
3864 if (menu_will_open_state == MENU_OPENING)
3865 menu_will_open_state = MENU_NONE;
3869 for (i = 0; ! found && i < [a count]; i++)
3870 found = menu == [[a objectAtIndex:i] submenu];
3873 if (menu_will_open_state == MENU_NONE && emacs_event)
3875 NSEvent *theEvent = [NSApp currentEvent];
3876 struct frame *emacsframe = SELECTED_FRAME ();
3878 [menu cancelTracking];
3879 menu_will_open_state = MENU_PENDING;
3880 emacs_event->kind = MENU_BAR_ACTIVATE_EVENT;
3881 EV_TRAILER (theEvent);
3883 CGEventRef ourEvent = CGEventCreate (NULL);
3884 menu_mouse_point = CGEventGetLocation (ourEvent);
3885 CFRelease (ourEvent);
3887 else if (menu_will_open_state == MENU_OPENING)
3889 menu_will_open_state = MENU_NONE;
3894 /* Redo saved menu click if state is MENU_PENDING. */
3896 ns_check_pending_open_menu ()
3898 if (menu_will_open_state == MENU_PENDING)
3900 CGEventSourceRef source
3901 = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
3903 CGEventRef event = CGEventCreateMouseEvent (source,
3904 kCGEventLeftMouseDown,
3906 kCGMouseButtonLeft);
3907 CGEventSetType (event, kCGEventLeftMouseDown);
3908 CGEventPost (kCGHIDEventTap, event);
3912 menu_will_open_state = MENU_OPENING;
3915 #endif /* NS_IMPL_COCOA */
3918 unwind_apploopnr (Lisp_Object not_used)
3921 n_emacs_events_pending = 0;
3922 ns_finish_events ();
3927 ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3928 /* --------------------------------------------------------------------------
3929 External (hook): Post an event to ourself and keep reading events until
3930 we read it back again. In effect process all events which were waiting.
3931 From 21+ we have to manage the event buffer ourselves.
3932 -------------------------------------------------------------------------- */
3934 struct input_event ev;
3937 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_read_socket");
3939 #ifdef HAVE_NATIVE_FS
3943 if ([NSApp modalWindow] != nil)
3946 if (hold_event_q.nr > 0)
3949 for (i = 0; i < hold_event_q.nr; ++i)
3950 kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit);
3951 hold_event_q.nr = 0;
3956 n_emacs_events_pending = 0;
3957 ns_init_events (&ev);
3958 q_event_ptr = hold_quit;
3960 /* we manage autorelease pools by allocate/reallocate each time around
3961 the loop; strict nesting is occasionally violated but seems not to
3962 matter.. earlier methods using full nesting caused major memory leaks */
3963 [outerpool release];
3964 outerpool = [[NSAutoreleasePool alloc] init];
3966 /* If have pending open-file requests, attend to the next one of those. */
3967 if (ns_pending_files && [ns_pending_files count] != 0
3968 && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]])
3970 [ns_pending_files removeObjectAtIndex: 0];
3972 /* Deal with pending service requests. */
3973 else if (ns_pending_service_names && [ns_pending_service_names count] != 0
3975 NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
3976 withArg: [ns_pending_service_args objectAtIndex: 0]])
3978 [ns_pending_service_names removeObjectAtIndex: 0];
3979 [ns_pending_service_args removeObjectAtIndex: 0];
3983 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
3984 /* Run and wait for events. We must always send one NX_APPDEFINED event
3985 to ourself, otherwise [NXApp run] will never exit. */
3986 send_appdefined = YES;
3987 ns_send_appdefined (-1);
3989 if (++apploopnr != 1)
3993 record_unwind_protect (unwind_apploopnr, Qt);
3995 unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */
3998 nevents = n_emacs_events_pending;
3999 n_emacs_events_pending = 0;
4000 ns_finish_events ();
4009 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4010 fd_set *exceptfds, struct timespec const *timeout,
4011 sigset_t const *sigmask)
4012 /* --------------------------------------------------------------------------
4013 Replacement for select, checking for events
4014 -------------------------------------------------------------------------- */
4018 struct input_event event;
4021 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_select");
4023 #ifdef HAVE_NATIVE_FS
4027 if (hold_event_q.nr > 0)
4029 /* We already have events pending. */
4035 for (k = 0; k < nfds+1; k++)
4037 if (readfds && FD_ISSET(k, readfds)) ++nr;
4038 if (writefds && FD_ISSET(k, writefds)) ++nr;
4042 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
4043 return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
4045 [outerpool release];
4046 outerpool = [[NSAutoreleasePool alloc] init];
4049 send_appdefined = YES;
4052 pthread_mutex_lock (&select_mutex);
4057 select_readfds = *readfds;
4058 select_valid += SELECT_HAVE_READ;
4062 select_writefds = *writefds;
4063 select_valid += SELECT_HAVE_WRITE;
4068 select_timeout = *timeout;
4069 select_valid += SELECT_HAVE_TMO;
4072 pthread_mutex_unlock (&select_mutex);
4074 /* Inform fd_handler that select should be called */
4076 emacs_write_sig (selfds[1], &c, 1);
4078 else if (nr == 0 && timeout)
4080 /* No file descriptor, just a timeout, no need to wake fd_handler */
4081 double time = timespectod (*timeout);
4082 timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
4085 @selector (timeout_handler:)
4090 else /* No timeout and no file descriptors, can this happen? */
4092 /* Send appdefined so we exit from the loop */
4093 ns_send_appdefined (-1);
4097 ns_init_events (&event);
4098 if (++apploopnr != 1)
4104 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
4105 record_unwind_protect (unwind_apploopnr, Qt);
4107 unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */
4110 ns_finish_events ();
4111 if (nr > 0 && readfds)
4114 emacs_write_sig (selfds[1], &c, 1);
4118 t = last_appdefined_event_data;
4120 if (t != NO_APPDEFINED_DATA)
4122 last_appdefined_event_data = NO_APPDEFINED_DATA;
4126 /* The NX_APPDEFINED event we received was a timeout. */
4131 /* The NX_APPDEFINED event we received was the result of
4132 at least one real input event arriving. */
4138 /* Received back from select () in fd_handler; copy the results */
4139 pthread_mutex_lock (&select_mutex);
4140 if (readfds) *readfds = select_readfds;
4141 if (writefds) *writefds = select_writefds;
4142 pthread_mutex_unlock (&select_mutex);
4157 /* ==========================================================================
4161 ========================================================================== */
4165 ns_set_vertical_scroll_bar (struct window *window,
4166 int portion, int whole, int position)
4167 /* --------------------------------------------------------------------------
4168 External (hook): Update or add scrollbar
4169 -------------------------------------------------------------------------- */
4173 struct frame *f = XFRAME (WINDOW_FRAME (window));
4174 EmacsView *view = FRAME_NS_VIEW (f);
4176 int window_y, window_height;
4177 int top, left, height, width;
4178 BOOL update_p = YES;
4180 /* optimization; display engine sends WAY too many of these.. */
4181 if (!NILP (window->vertical_scroll_bar))
4183 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4184 if ([bar checkSamePosition: position portion: portion whole: whole])
4186 if (view->scrollbarsNeedingUpdate == 0)
4188 if (!windows_or_buffers_changed)
4192 view->scrollbarsNeedingUpdate--;
4197 NSTRACE ("ns_set_vertical_scroll_bar");
4199 /* Get dimensions. */
4200 window_box (window, ANY_AREA, 0, &window_y, 0, &window_height);
4202 height = window_height;
4203 width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
4204 left = WINDOW_SCROLL_BAR_AREA_X (window);
4206 r = NSMakeRect (left, top, width, height);
4207 /* the parent view is flipped, so we need to flip y value */
4209 r.origin.y = (v.size.height - r.size.height - r.origin.y);
4211 XSETWINDOW (win, window);
4214 /* we want at least 5 lines to display a scrollbar */
4215 if (WINDOW_TOTAL_LINES (window) < 5)
4217 if (!NILP (window->vertical_scroll_bar))
4219 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4220 [bar removeFromSuperview];
4221 wset_vertical_scroll_bar (window, Qnil);
4224 ns_clear_frame_area (f, left, top, width, height);
4229 if (NILP (window->vertical_scroll_bar))
4231 if (width > 0 && height > 0)
4232 ns_clear_frame_area (f, left, top, width, height);
4234 bar = [[EmacsScroller alloc] initFrame: r window: win];
4235 wset_vertical_scroll_bar (window, make_save_ptr (bar));
4241 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4242 oldRect = [bar frame];
4243 r.size.width = oldRect.size.width;
4244 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
4246 if (oldRect.origin.x != r.origin.x)
4247 ns_clear_frame_area (f, left, top, width, height);
4253 [bar setPosition: position portion: portion whole: whole];
4259 ns_set_horizontal_scroll_bar (struct window *window,
4260 int portion, int whole, int position)
4261 /* --------------------------------------------------------------------------
4262 External (hook): Update or add scrollbar
4263 -------------------------------------------------------------------------- */
4267 struct frame *f = XFRAME (WINDOW_FRAME (window));
4268 EmacsView *view = FRAME_NS_VIEW (f);
4270 int top, height, left, width;
4271 int window_x, window_width;
4272 BOOL update_p = YES;
4274 /* optimization; display engine sends WAY too many of these.. */
4275 if (!NILP (window->horizontal_scroll_bar))
4277 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4278 if ([bar checkSamePosition: position portion: portion whole: whole])
4280 if (view->scrollbarsNeedingUpdate == 0)
4282 if (!windows_or_buffers_changed)
4286 view->scrollbarsNeedingUpdate--;
4291 NSTRACE ("ns_set_horizontal_scroll_bar");
4293 /* Get dimensions. */
4294 window_box (window, ANY_AREA, 0, &window_x, &window_width, 0);
4296 width = window_width;
4297 height = WINDOW_CONFIG_SCROLL_BAR_LINES (window) * FRAME_LINE_HEIGHT (f);
4298 top = WINDOW_SCROLL_BAR_AREA_Y (window);
4300 r = NSMakeRect (left, top, width, height);
4301 /* the parent view is flipped, so we need to flip y value */
4303 /* ??????? PXW/scrollbars !!!!!!!!!!!!!!!!!!!! */
4304 r.origin.y = (v.size.height - r.size.height - r.origin.y);
4306 XSETWINDOW (win, window);
4309 if (WINDOW_TOTAL_COLS (window) < 5)
4311 if (!NILP (window->horizontal_scroll_bar))
4313 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4314 [bar removeFromSuperview];
4315 wset_horizontal_scroll_bar (window, Qnil);
4317 ns_clear_frame_area (f, left, top, width, height);
4322 if (NILP (window->horizontal_scroll_bar))
4324 if (width > 0 && height > 0)
4325 ns_clear_frame_area (f, left, top, width, height);
4327 bar = [[EmacsScroller alloc] initFrame: r window: win];
4328 wset_horizontal_scroll_bar (window, make_save_ptr (bar));
4334 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4335 oldRect = [bar frame];
4336 r.size.width = oldRect.size.width;
4337 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
4339 if (oldRect.origin.x != r.origin.x)
4340 ns_clear_frame_area (f, left, top, width, height);
4347 [bar setPosition: position portion: portion whole: whole];
4353 ns_condemn_scroll_bars (struct frame *f)
4354 /* --------------------------------------------------------------------------
4355 External (hook): arrange for all frame's scrollbars to be removed
4356 at next call to judge_scroll_bars, except for those redeemed.
4357 -------------------------------------------------------------------------- */
4361 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
4363 NSTRACE ("ns_condemn_scroll_bars");
4365 for (i =[subviews count]-1; i >= 0; i--)
4367 view = [subviews objectAtIndex: i];
4368 if ([view isKindOfClass: [EmacsScroller class]])
4375 ns_redeem_scroll_bar (struct window *window)
4376 /* --------------------------------------------------------------------------
4377 External (hook): arrange to spare this window's scrollbar
4378 at next call to judge_scroll_bars.
4379 -------------------------------------------------------------------------- */
4382 NSTRACE ("ns_redeem_scroll_bar");
4383 if (!NILP (window->vertical_scroll_bar))
4385 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
4389 if (!NILP (window->horizontal_scroll_bar))
4391 bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
4398 ns_judge_scroll_bars (struct frame *f)
4399 /* --------------------------------------------------------------------------
4400 External (hook): destroy all scrollbars on frame that weren't
4401 redeemed after call to condemn_scroll_bars.
4402 -------------------------------------------------------------------------- */
4406 EmacsView *eview = FRAME_NS_VIEW (f);
4407 NSArray *subviews = [[eview superview] subviews];
4410 NSTRACE ("ns_judge_scroll_bars");
4411 for (i = [subviews count]-1; i >= 0; --i)
4413 view = [subviews objectAtIndex: i];
4414 if (![view isKindOfClass: [EmacsScroller class]]) continue;
4420 [eview updateFrameSize: NO];
4423 /* ==========================================================================
4427 ========================================================================== */
4430 x_display_pixel_height (struct ns_display_info *dpyinfo)
4432 NSArray *screens = [NSScreen screens];
4433 NSEnumerator *enumerator = [screens objectEnumerator];
4438 while ((screen = [enumerator nextObject]) != nil)
4439 frame = NSUnionRect (frame, [screen frame]);
4441 return NSHeight (frame);
4445 x_display_pixel_width (struct ns_display_info *dpyinfo)
4447 NSArray *screens = [NSScreen screens];
4448 NSEnumerator *enumerator = [screens objectEnumerator];
4453 while ((screen = [enumerator nextObject]) != nil)
4454 frame = NSUnionRect (frame, [screen frame]);
4456 return NSWidth (frame);
4460 static Lisp_Object ns_string_to_lispmod (const char *s)
4461 /* --------------------------------------------------------------------------
4462 Convert modifier name to lisp symbol
4463 -------------------------------------------------------------------------- */
4465 if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10))
4467 else if (!strncmp (SSDATA (SYMBOL_NAME (Qsuper)), s, 10))
4469 else if (!strncmp (SSDATA (SYMBOL_NAME (Qcontrol)), s, 10))
4471 else if (!strncmp (SSDATA (SYMBOL_NAME (Qalt)), s, 10))
4473 else if (!strncmp (SSDATA (SYMBOL_NAME (Qhyper)), s, 10))
4475 else if (!strncmp (SSDATA (SYMBOL_NAME (Qnone)), s, 10))
4483 ns_default (const char *parameter, Lisp_Object *result,
4484 Lisp_Object yesval, Lisp_Object noval,
4485 BOOL is_float, BOOL is_modstring)
4486 /* --------------------------------------------------------------------------
4487 Check a parameter value in user's preferences
4488 -------------------------------------------------------------------------- */
4490 const char *value = ns_get_defaults_value (parameter);
4496 if (c_strcasecmp (value, "YES") == 0)
4498 else if (c_strcasecmp (value, "NO") == 0)
4500 else if (is_float && (f = strtod (value, &pos), pos != value))
4501 *result = make_float (f);
4502 else if (is_modstring && value)
4503 *result = ns_string_to_lispmod (value);
4504 else fprintf (stderr,
4505 "Bad value for default \"%s\": \"%s\"\n", parameter, value);
4511 ns_initialize_display_info (struct ns_display_info *dpyinfo)
4512 /* --------------------------------------------------------------------------
4513 Initialize global info and storage for display.
4514 -------------------------------------------------------------------------- */
4516 NSScreen *screen = [NSScreen mainScreen];
4517 NSWindowDepth depth = [screen depth];
4519 dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
4520 dpyinfo->resy = 72.27;
4521 dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
4522 NSColorSpaceFromDepth (depth)]
4523 && ![NSCalibratedWhiteColorSpace isEqualToString:
4524 NSColorSpaceFromDepth (depth)];
4525 dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
4526 dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table);
4527 dpyinfo->color_table->colors = NULL;
4528 dpyinfo->root_window = 42; /* a placeholder.. */
4529 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL;
4530 dpyinfo->n_fonts = 0;
4531 dpyinfo->smallest_font_height = 1;
4532 dpyinfo->smallest_char_width = 1;
4534 reset_mouse_highlight (&dpyinfo->mouse_highlight);
4538 /* This and next define (many of the) public functions in this file. */
4539 /* x_... are generic versions in xdisp.c that we, and other terms, get away
4540 with using despite presence in the "system dependent" redisplay
4541 interface. In addition, many of the ns_ methods have code that is
4542 shared with all terms, indicating need for further refactoring. */
4543 extern frame_parm_handler ns_frame_parm_handlers[];
4544 static struct redisplay_interface ns_redisplay_interface =
4546 ns_frame_parm_handlers,
4550 x_clear_end_of_line,
4552 ns_after_update_window_line,
4553 ns_update_window_begin,
4554 ns_update_window_end,
4555 0, /* flush_display */
4556 x_clear_window_mouse_face,
4557 x_get_glyph_overhangs,
4558 x_fix_overlapping_area,
4559 ns_draw_fringe_bitmap,
4560 0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
4561 0, /* destroy_fringe_bitmap */
4562 ns_compute_glyph_string_overhangs,
4563 ns_draw_glyph_string,
4564 ns_define_frame_cursor,
4565 ns_clear_frame_area,
4566 ns_draw_window_cursor,
4567 ns_draw_vertical_window_border,
4568 ns_draw_window_divider,
4569 ns_shift_glyphs_for_insert,
4576 ns_delete_display (struct ns_display_info *dpyinfo)
4582 /* This function is called when the last frame on a display is deleted. */
4584 ns_delete_terminal (struct terminal *terminal)
4586 struct ns_display_info *dpyinfo = terminal->display_info.ns;
4588 NSTRACE ("ns_delete_terminal");
4590 /* Protect against recursive calls. delete_frame in
4591 delete_terminal calls us back when it deletes our last frame. */
4592 if (!terminal->name)
4597 x_destroy_all_bitmaps (dpyinfo);
4598 ns_delete_display (dpyinfo);
4603 static struct terminal *
4604 ns_create_terminal (struct ns_display_info *dpyinfo)
4605 /* --------------------------------------------------------------------------
4606 Set up use of NS before we make the first connection.
4607 -------------------------------------------------------------------------- */
4609 struct terminal *terminal;
4611 NSTRACE ("ns_create_terminal");
4613 terminal = create_terminal (output_ns, &ns_redisplay_interface);
4615 terminal->display_info.ns = dpyinfo;
4616 dpyinfo->terminal = terminal;
4618 terminal->clear_frame_hook = ns_clear_frame;
4619 terminal->ring_bell_hook = ns_ring_bell;
4620 terminal->update_begin_hook = ns_update_begin;
4621 terminal->update_end_hook = ns_update_end;
4622 terminal->read_socket_hook = ns_read_socket;
4623 terminal->frame_up_to_date_hook = ns_frame_up_to_date;
4624 terminal->mouse_position_hook = ns_mouse_position;
4625 terminal->frame_rehighlight_hook = ns_frame_rehighlight;
4626 terminal->frame_raise_lower_hook = ns_frame_raise_lower;
4627 terminal->fullscreen_hook = ns_fullscreen_hook;
4628 terminal->menu_show_hook = ns_menu_show;
4629 terminal->popup_dialog_hook = ns_popup_dialog;
4630 terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
4631 terminal->set_horizontal_scroll_bar_hook = ns_set_horizontal_scroll_bar;
4632 terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
4633 terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
4634 terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
4635 terminal->delete_frame_hook = x_destroy_window;
4636 terminal->delete_terminal_hook = ns_delete_terminal;
4637 /* Other hooks are NULL by default. */
4643 struct ns_display_info *
4644 ns_term_init (Lisp_Object display_name)
4645 /* --------------------------------------------------------------------------
4646 Start the Application and get things rolling.
4647 -------------------------------------------------------------------------- */
4649 struct terminal *terminal;
4650 struct ns_display_info *dpyinfo;
4651 static int ns_initialized = 0;
4654 if (ns_initialized) return x_display_list;
4659 NSTRACE ("ns_term_init");
4661 [outerpool release];
4662 outerpool = [[NSAutoreleasePool alloc] init];
4664 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
4665 /*GSDebugAllocationActive (YES); */
4669 Fset_input_interrupt_mode (Qnil);
4671 if (selfds[0] == -1)
4673 if (emacs_pipe (selfds) != 0)
4675 fprintf (stderr, "Failed to create pipe: %s\n",
4676 emacs_strerror (errno));
4680 fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
4681 FD_ZERO (&select_readfds);
4682 FD_ZERO (&select_writefds);
4683 pthread_mutex_init (&select_mutex, NULL);
4686 ns_pending_files = [[NSMutableArray alloc] init];
4687 ns_pending_service_names = [[NSMutableArray alloc] init];
4688 ns_pending_service_args = [[NSMutableArray alloc] init];
4690 /* Start app and create the main menu, window, view.
4691 Needs to be here because ns_initialize_display_info () uses AppKit classes.
4692 The view will then ask the NSApp to stop and return to Emacs. */
4693 [EmacsApp sharedApplication];
4696 [NSApp setDelegate: NSApp];
4698 /* Start the select thread. */
4699 [NSThread detachNewThreadSelector:@selector (fd_handler:)
4703 /* debugging: log all notifications */
4704 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
4705 selector: @selector (logNotification:)
4706 name: nil object: nil]; */
4708 dpyinfo = xzalloc (sizeof *dpyinfo);
4710 ns_initialize_display_info (dpyinfo);
4711 terminal = ns_create_terminal (dpyinfo);
4713 terminal->kboard = allocate_kboard (Qns);
4714 /* Don't let the initial kboard remain current longer than necessary.
4715 That would cause problems if a file loaded on startup tries to
4716 prompt in the mini-buffer. */
4717 if (current_kboard == initial_kboard)
4718 current_kboard = terminal->kboard;
4719 terminal->kboard->reference_count++;
4721 dpyinfo->next = x_display_list;
4722 x_display_list = dpyinfo;
4724 dpyinfo->name_list_element = Fcons (display_name, Qnil);
4726 terminal->name = xlispstrdup (display_name);
4730 if (!inhibit_x_resources)
4732 ns_default ("GSFontAntiAlias", &ns_antialias_text,
4735 /* this is a standard variable */
4736 ns_default ("AppleAntiAliasingThreshold", &tmp,
4737 make_float (10.0), make_float (6.0), YES, NO);
4738 ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
4741 NSTRACE_MSG ("Colors");
4744 NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
4748 Lisp_Object color_file, color_map, color;
4752 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4753 Fsymbol_value (intern ("data-directory")));
4755 color_map = Fx_load_color_file (color_file);
4756 if (NILP (color_map))
4757 fatal ("Could not read %s.\n", SDATA (color_file));
4759 cl = [[NSColorList alloc] initWithName: @"Emacs"];
4760 for ( ; CONSP (color_map); color_map = XCDR (color_map))
4762 color = XCAR (color_map);
4763 name = SSDATA (XCAR (color));
4764 c = XINT (XCDR (color));
4766 [NSColor colorForEmacsRed: RED_FROM_ULONG (c) / 255.0
4767 green: GREEN_FROM_ULONG (c) / 255.0
4768 blue: BLUE_FROM_ULONG (c) / 255.0
4770 forKey: [NSString stringWithUTF8String: name]];
4772 [cl writeToFile: nil];
4776 NSTRACE_MSG ("Versions");
4779 #ifdef NS_IMPL_GNUSTEP
4780 Vwindow_system_version = build_string (gnustep_base_version);
4782 /*PSnextrelease (128, c); */
4783 char c[DBL_BUFSIZE_BOUND];
4784 int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber);
4785 Vwindow_system_version = make_unibyte_string (c, len);
4789 delete_keyboard_wait_descriptor (0);
4791 ns_app_name = [[NSProcessInfo processInfo] processName];
4793 /* Set up OS X app menu */
4795 NSTRACE_MSG ("Menu init");
4797 #ifdef NS_IMPL_COCOA
4801 /* set up the application menu */
4802 svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
4803 [svcsMenu setAutoenablesItems: NO];
4804 appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
4805 [appMenu setAutoenablesItems: NO];
4806 mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
4807 dockMenu = [[EmacsMenu alloc] initWithTitle: @""];
4809 [appMenu insertItemWithTitle: @"About Emacs"
4810 action: @selector (orderFrontStandardAboutPanel:)
4813 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
4814 [appMenu insertItemWithTitle: @"Preferences..."
4815 action: @selector (showPreferencesWindow:)
4818 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
4819 item = [appMenu insertItemWithTitle: @"Services"
4820 action: @selector (menuDown:)
4823 [appMenu setSubmenu: svcsMenu forItem: item];
4824 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];
4825 [appMenu insertItemWithTitle: @"Hide Emacs"
4826 action: @selector (hide:)
4829 item = [appMenu insertItemWithTitle: @"Hide Others"
4830 action: @selector (hideOtherApplications:)
4833 [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
4834 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8];
4835 [appMenu insertItemWithTitle: @"Quit Emacs"
4836 action: @selector (terminate:)
4840 item = [mainMenu insertItemWithTitle: ns_app_name
4841 action: @selector (menuDown:)
4844 [mainMenu setSubmenu: appMenu forItem: item];
4845 [dockMenu insertItemWithTitle: @"New Frame"
4846 action: @selector (newFrame:)
4850 [NSApp setMainMenu: mainMenu];
4851 [NSApp setAppleMenu: appMenu];
4852 [NSApp setServicesMenu: svcsMenu];
4853 /* Needed at least on Cocoa, to get dock menu to show windows */
4854 [NSApp setWindowsMenu: [[NSMenu alloc] init]];
4856 [[NSNotificationCenter defaultCenter]
4857 addObserver: mainMenu
4858 selector: @selector (trackingNotification:)
4859 name: NSMenuDidBeginTrackingNotification object: mainMenu];
4860 [[NSNotificationCenter defaultCenter]
4861 addObserver: mainMenu
4862 selector: @selector (trackingNotification:)
4863 name: NSMenuDidEndTrackingNotification object: mainMenu];
4865 #endif /* MAC OS X menu setup */
4867 /* Register our external input/output types, used for determining
4868 applicable services and also drag/drop eligibility. */
4870 NSTRACE_MSG ("Input/output types");
4872 ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
4873 ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
4875 ns_drag_types = [[NSArray arrayWithObjects:
4877 NSTabularTextPboardType,
4878 NSFilenamesPboardType,
4879 NSURLPboardType, nil] retain];
4881 /* If fullscreen is in init/default-frame-alist, focus isn't set
4882 right for fullscreen windows, so set this. */
4883 [NSApp activateIgnoringOtherApps:YES];
4885 NSTRACE_MSG ("Call NSApp run");
4888 ns_do_open_file = YES;
4890 #ifdef NS_IMPL_GNUSTEP
4891 /* GNUstep steals SIGCHLD for use in NSTask, but we don't use NSTask.
4892 We must re-catch it so subprocess works. */
4893 catch_child_signal ();
4896 NSTRACE_MSG ("ns_term_init done");
4905 ns_term_shutdown (int sig)
4907 [[NSUserDefaults standardUserDefaults] synchronize];
4909 /* code not reached in emacs.c after this is called by shut_down_emacs: */
4910 if (STRINGP (Vauto_save_list_file_name))
4911 unlink (SSDATA (Vauto_save_list_file_name));
4913 if (sig == 0 || sig == SIGTERM)
4915 [NSApp terminate: NSApp];
4917 else // force a stack trace to happen
4924 /* ==========================================================================
4926 EmacsApp implementation
4928 ========================================================================== */
4931 @implementation EmacsApp
4935 NSTRACE ("[EmacsApp init]");
4937 if ((self = [super init]))
4939 #ifdef NS_IMPL_COCOA
4940 self->isFirst = YES;
4942 #ifdef NS_IMPL_GNUSTEP
4943 self->applicationDidFinishLaunchingCalled = NO;
4950 #ifdef NS_IMPL_COCOA
4953 NSTRACE ("[EmacsApp run]");
4955 #ifndef NSAppKitVersionNumber10_9
4956 #define NSAppKitVersionNumber10_9 1265
4959 if ((int)NSAppKitVersionNumber != NSAppKitVersionNumber10_9)
4965 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4967 if (isFirst) [self finishLaunching];
4970 shouldKeepRunning = YES;
4974 pool = [[NSAutoreleasePool alloc] init];
4977 [self nextEventMatchingMask:NSAnyEventMask
4978 untilDate:[NSDate distantFuture]
4979 inMode:NSDefaultRunLoopMode
4982 [self sendEvent:event];
4983 [self updateWindows];
4984 } while (shouldKeepRunning);
4989 - (void)stop: (id)sender
4991 NSTRACE ("[EmacsApp stop:]");
4993 shouldKeepRunning = NO;
4994 // Stop possible dialog also. Noop if no dialog present.
4995 // The file dialog still leaks 7k - 10k on 10.9 though.
4996 [super stop:sender];
4998 #endif /* NS_IMPL_COCOA */
5000 - (void)logNotification: (NSNotification *)notification
5002 NSTRACE ("[EmacsApp logNotification:]");
5004 const char *name = [[notification name] UTF8String];
5005 if (!strstr (name, "Update") && !strstr (name, "NSMenu")
5006 && !strstr (name, "WindowNumber"))
5007 NSLog (@"notification: '%@'", [notification name]);
5011 - (void)sendEvent: (NSEvent *)theEvent
5012 /* --------------------------------------------------------------------------
5013 Called when NSApp is running for each event received. Used to stop
5014 the loop when we choose, since there's no way to just run one iteration.
5015 -------------------------------------------------------------------------- */
5017 int type = [theEvent type];
5018 NSWindow *window = [theEvent window];
5020 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsApp sendEvent:]");
5021 NSTRACE_MSG ("Type: %d", type);
5023 #ifdef NS_IMPL_GNUSTEP
5024 // Keyboard events aren't propagated to file dialogs for some reason.
5025 if ([NSApp modalWindow] != nil &&
5026 (type == NSKeyDown || type == NSKeyUp || type == NSFlagsChanged))
5028 [[NSApp modalWindow] sendEvent: theEvent];
5033 if (represented_filename != nil && represented_frame)
5035 NSString *fstr = represented_filename;
5036 NSView *view = FRAME_NS_VIEW (represented_frame);
5037 #ifdef NS_IMPL_COCOA
5038 /* work around a bug observed on 10.3 and later where
5039 setTitleWithRepresentedFilename does not clear out previous state
5040 if given filename does not exist */
5041 if (! [[NSFileManager defaultManager] fileExistsAtPath: fstr])
5042 [[view window] setRepresentedFilename: @""];
5044 [[view window] setRepresentedFilename: fstr];
5045 [represented_filename release];
5046 represented_filename = nil;
5047 represented_frame = NULL;
5050 if (type == NSApplicationDefined)
5052 switch ([theEvent data2])
5054 #ifdef NS_IMPL_COCOA
5055 case NSAPP_DATA2_RUNASSCRIPT:
5060 case NSAPP_DATA2_RUNFILEDIALOG:
5061 ns_run_file_dialog ();
5067 if (type == NSCursorUpdate && window == nil)
5069 fprintf (stderr, "Dropping external cursor update event.\n");
5073 if (type == NSApplicationDefined)
5075 /* Events posted by ns_send_appdefined interrupt the run loop here.
5076 But, if a modal window is up, an appdefined can still come through,
5077 (e.g., from a makeKeyWindow event) but stopping self also stops the
5078 modal loop. Just defer it until later. */
5079 if ([NSApp modalWindow] == nil)
5081 last_appdefined_event_data = [theEvent data1];
5086 send_appdefined = YES;
5091 #ifdef NS_IMPL_COCOA
5092 /* If no dialog and none of our frames have focus and it is a move, skip it.
5093 It is a mouse move in an auxiliary menu, i.e. on the top right on OSX,
5094 such as Wifi, sound, date or similar.
5095 This prevents "spooky" highlighting in the frame under the menu. */
5096 if (type == NSMouseMoved && [NSApp modalWindow] == nil)
5098 struct ns_display_info *di;
5099 BOOL has_focus = NO;
5100 for (di = x_display_list; ! has_focus && di; di = di->next)
5101 has_focus = di->x_focus_frame != 0;
5107 NSTRACE_UNSILENCE();
5109 [super sendEvent: theEvent];
5113 - (void)showPreferencesWindow: (id)sender
5115 struct frame *emacsframe = SELECTED_FRAME ();
5116 NSEvent *theEvent = [NSApp currentEvent];
5120 emacs_event->kind = NS_NONKEY_EVENT;
5121 emacs_event->code = KEY_NS_SHOW_PREFS;
5122 emacs_event->modifiers = 0;
5123 EV_TRAILER (theEvent);
5127 - (void)newFrame: (id)sender
5129 NSTRACE ("[EmacsApp newFrame:]");
5131 struct frame *emacsframe = SELECTED_FRAME ();
5132 NSEvent *theEvent = [NSApp currentEvent];
5136 emacs_event->kind = NS_NONKEY_EVENT;
5137 emacs_event->code = KEY_NS_NEW_FRAME;
5138 emacs_event->modifiers = 0;
5139 EV_TRAILER (theEvent);
5143 /* Open a file (used by below, after going into queue read by ns_read_socket) */
5144 - (BOOL) openFile: (NSString *)fileName
5146 NSTRACE ("[EmacsApp openFile:]");
5148 struct frame *emacsframe = SELECTED_FRAME ();
5149 NSEvent *theEvent = [NSApp currentEvent];
5154 emacs_event->kind = NS_NONKEY_EVENT;
5155 emacs_event->code = KEY_NS_OPEN_FILE_LINE;
5156 ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
5157 ns_input_line = Qnil; /* can be start or cons start,end */
5158 emacs_event->modifiers =0;
5159 EV_TRAILER (theEvent);
5165 /* **************************************************************************
5167 EmacsApp delegate implementation
5169 ************************************************************************** */
5171 - (void)applicationDidFinishLaunching: (NSNotification *)notification
5172 /* --------------------------------------------------------------------------
5173 When application is loaded, terminate event loop in ns_term_init
5174 -------------------------------------------------------------------------- */
5176 NSTRACE ("[EmacsApp applicationDidFinishLaunching:]");
5178 #ifdef NS_IMPL_GNUSTEP
5179 ((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES;
5181 [NSApp setServicesProvider: NSApp];
5183 [self antialiasThresholdDidChange:nil];
5184 #ifdef NS_IMPL_COCOA
5185 [[NSNotificationCenter defaultCenter]
5187 selector:@selector(antialiasThresholdDidChange:)
5188 name:NSAntialiasThresholdChangedNotification
5192 ns_send_appdefined (-2);
5195 - (void)antialiasThresholdDidChange:(NSNotification *)notification
5197 #ifdef NS_IMPL_COCOA
5198 macfont_update_antialias_threshold ();
5203 /* Termination sequences:
5206 MenuBar | File | Exit:
5207 Select Quit from App menubar:
5209 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
5212 Select Quit from Dock menu:
5215 Cancel -> Nothing else
5219 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
5224 - (void) terminate: (id)sender
5226 NSTRACE ("[EmacsApp terminate:]");
5228 struct frame *emacsframe = SELECTED_FRAME ();
5233 emacs_event->kind = NS_NONKEY_EVENT;
5234 emacs_event->code = KEY_NS_POWER_OFF;
5235 emacs_event->arg = Qt; /* mark as non-key event */
5236 EV_TRAILER ((id)nil);
5240 runAlertPanel(NSString *title,
5241 NSString *msgFormat,
5242 NSString *defaultButton,
5243 NSString *alternateButton)
5245 #if !defined (NS_IMPL_COCOA) || \
5246 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
5247 return NSRunAlertPanel(title, msgFormat, defaultButton, alternateButton, nil)
5248 == NSAlertDefaultReturn;
5250 NSAlert *alert = [[NSAlert alloc] init];
5251 [alert setAlertStyle: NSCriticalAlertStyle];
5252 [alert setMessageText: msgFormat];
5253 [alert addButtonWithTitle: defaultButton];
5254 [alert addButtonWithTitle: alternateButton];
5255 NSInteger ret = [alert runModal];
5257 return ret == NSAlertFirstButtonReturn;
5262 - (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
5264 NSTRACE ("[EmacsApp applicationShouldTerminate:]");
5268 if (NILP (ns_confirm_quit)) // || ns_shutdown_properly --> TO DO
5269 return NSTerminateNow;
5271 ret = runAlertPanel(ns_app_name,
5272 @"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?",
5273 @"Save Buffers and Exit", @"Cancel");
5276 return NSTerminateNow;
5278 return NSTerminateCancel;
5279 return NSTerminateNow; /* just in case */
5283 not_in_argv (NSString *arg)
5286 const char *a = [arg UTF8String];
5287 for (k = 1; k < initial_argc; ++k)
5288 if (strcmp (a, initial_argv[k]) == 0) return 0;
5292 /* Notification from the Workspace to open a file */
5293 - (BOOL)application: sender openFile: (NSString *)file
5295 if (ns_do_open_file || not_in_argv (file))
5296 [ns_pending_files addObject: file];
5301 /* Open a file as a temporary file */
5302 - (BOOL)application: sender openTempFile: (NSString *)file
5304 if (ns_do_open_file || not_in_argv (file))
5305 [ns_pending_files addObject: file];
5310 /* Notification from the Workspace to open a file noninteractively (?) */
5311 - (BOOL)application: sender openFileWithoutUI: (NSString *)file
5313 if (ns_do_open_file || not_in_argv (file))
5314 [ns_pending_files addObject: file];
5318 /* Notification from the Workspace to open multiple files */
5319 - (void)application: sender openFiles: (NSArray *)fileList
5321 NSEnumerator *files = [fileList objectEnumerator];
5323 /* Don't open files from the command line unconditionally,
5324 Cocoa parses the command line wrong, --option value tries to open value
5325 if --option is the last option. */
5326 while ((file = [files nextObject]) != nil)
5327 if (ns_do_open_file || not_in_argv (file))
5328 [ns_pending_files addObject: file];
5330 [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
5335 /* Handle dock menu requests. */
5336 - (NSMenu *)applicationDockMenu: (NSApplication *) sender
5342 /* TODO: these may help w/IO switching btwn terminal and NSApp */
5343 - (void)applicationWillBecomeActive: (NSNotification *)notification
5345 NSTRACE ("[EmacsApp applicationWillBecomeActive:]");
5346 //ns_app_active=YES;
5349 - (void)applicationDidBecomeActive: (NSNotification *)notification
5351 NSTRACE ("[EmacsApp applicationDidBecomeActive:]");
5353 #ifdef NS_IMPL_GNUSTEP
5354 if (! applicationDidFinishLaunchingCalled)
5355 [self applicationDidFinishLaunching:notification];
5357 //ns_app_active=YES;
5359 ns_update_auto_hide_menu_bar ();
5360 // No constraining takes place when the application is not active.
5361 ns_constrain_all_frames ();
5363 - (void)applicationDidResignActive: (NSNotification *)notification
5365 NSTRACE ("[EmacsApp applicationDidResignActive:]");
5368 ns_send_appdefined (-1);
5373 /* ==========================================================================
5375 EmacsApp aux handlers for managing event loop
5377 ========================================================================== */
5380 - (void)timeout_handler: (NSTimer *)timedEntry
5381 /* --------------------------------------------------------------------------
5382 The timeout specified to ns_select has passed.
5383 -------------------------------------------------------------------------- */
5385 /*NSTRACE ("timeout_handler"); */
5386 ns_send_appdefined (-2);
5389 #ifdef NS_IMPL_GNUSTEP
5390 - (void)sendFromMainThread:(id)unused
5392 ns_send_appdefined (nextappdefined);
5396 - (void)fd_handler:(id)unused
5397 /* --------------------------------------------------------------------------
5398 Check data waiting on file descriptors and terminate if so
5399 -------------------------------------------------------------------------- */
5402 int waiting = 1, nfds;
5405 fd_set readfds, writefds, *wfds;
5406 struct timespec timeout, *tmo;
5407 NSAutoreleasePool *pool = nil;
5409 /* NSTRACE ("fd_handler"); */
5414 pool = [[NSAutoreleasePool alloc] init];
5420 FD_SET (selfds[0], &fds);
5421 result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
5422 if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
5427 pthread_mutex_lock (&select_mutex);
5430 if (select_valid & SELECT_HAVE_READ)
5431 readfds = select_readfds;
5435 if (select_valid & SELECT_HAVE_WRITE)
5437 writefds = select_writefds;
5442 if (select_valid & SELECT_HAVE_TMO)
5444 timeout = select_timeout;
5450 pthread_mutex_unlock (&select_mutex);
5452 FD_SET (selfds[0], &readfds);
5453 if (selfds[0] >= nfds) nfds = selfds[0]+1;
5455 result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL);
5458 ns_send_appdefined (-2);
5459 else if (result > 0)
5461 if (FD_ISSET (selfds[0], &readfds))
5463 if (read (selfds[0], &c, 1) == 1 && c == 's')
5468 pthread_mutex_lock (&select_mutex);
5469 if (select_valid & SELECT_HAVE_READ)
5470 select_readfds = readfds;
5471 if (select_valid & SELECT_HAVE_WRITE)
5472 select_writefds = writefds;
5473 if (select_valid & SELECT_HAVE_TMO)
5474 select_timeout = timeout;
5475 pthread_mutex_unlock (&select_mutex);
5477 ns_send_appdefined (result);
5487 /* ==========================================================================
5491 ========================================================================== */
5493 /* called from system: queue for next pass through event loop */
5494 - (void)requestService: (NSPasteboard *)pboard
5495 userData: (NSString *)userData
5496 error: (NSString **)error
5498 [ns_pending_service_names addObject: userData];
5499 [ns_pending_service_args addObject: [NSString stringWithUTF8String:
5500 SSDATA (ns_string_from_pasteboard (pboard))]];
5504 /* called from ns_read_socket to clear queue */
5505 - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
5507 struct frame *emacsframe = SELECTED_FRAME ();
5508 NSEvent *theEvent = [NSApp currentEvent];
5510 NSTRACE ("[EmacsApp fulfillService:withArg:]");
5515 emacs_event->kind = NS_NONKEY_EVENT;
5516 emacs_event->code = KEY_NS_SPI_SERVICE_CALL;
5517 ns_input_spi_name = build_string ([name UTF8String]);
5518 ns_input_spi_arg = build_string ([arg UTF8String]);
5519 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5520 EV_TRAILER (theEvent);
5530 /* ==========================================================================
5532 EmacsView implementation
5534 ========================================================================== */
5537 @implementation EmacsView
5539 /* needed to inform when window closed from LISP */
5540 - (void) setWindowClosing: (BOOL)closing
5542 NSTRACE ("[EmacsView setWindowClosing:%d]", closing);
5544 windowClosing = closing;
5550 NSTRACE ("[EmacsView dealloc]");
5552 if (fs_state == FULLSCREEN_BOTH)
5553 [nonfs_window release];
5558 /* called on font panel selection */
5559 - (void)changeFont: (id)sender
5561 NSEvent *e = [[self window] currentEvent];
5562 struct face *face = FRAME_DEFAULT_FACE (emacsframe);
5563 struct font *font = face->font;
5568 NSTRACE ("[EmacsView changeFont:]");
5573 #ifdef NS_IMPL_GNUSTEP
5574 nsfont = ((struct nsfont_info *)font)->nsfont;
5576 #ifdef NS_IMPL_COCOA
5577 nsfont = (NSFont *) macfont_get_nsctfont (font);
5580 if ((newFont = [sender convertFont: nsfont]))
5582 SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
5584 emacs_event->kind = NS_NONKEY_EVENT;
5585 emacs_event->modifiers = 0;
5586 emacs_event->code = KEY_NS_CHANGE_FONT;
5588 size = [newFont pointSize];
5589 ns_input_fontsize = make_number (lrint (size));
5590 ns_input_font = build_string ([[newFont familyName] UTF8String]);
5596 - (BOOL)acceptsFirstResponder
5598 NSTRACE ("[EmacsView acceptsFirstResponder]");
5603 - (void)resetCursorRects
5605 NSRect visible = [self visibleRect];
5606 NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
5607 NSTRACE ("[EmacsView resetCursorRects]");
5609 if (currentCursor == nil)
5610 currentCursor = [NSCursor arrowCursor];
5612 if (!NSIsEmptyRect (visible))
5613 [self addCursorRect: visible cursor: currentCursor];
5614 [currentCursor setOnMouseEntered: YES];
5619 /*****************************************************************************/
5620 /* Keyboard handling. */
5623 - (void)keyDown: (NSEvent *)theEvent
5625 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
5627 unsigned fnKeysym = 0;
5628 static NSMutableArray *nsEvArray;
5630 unsigned int flags = [theEvent modifierFlags];
5632 NSTRACE ("[EmacsView keyDown:]");
5634 /* Rhapsody and OS X give up and down events for the arrow keys */
5635 if (ns_fake_keydown == YES)
5636 ns_fake_keydown = NO;
5637 else if ([theEvent type] != NSKeyDown)
5643 if (![[self window] isKeyWindow]
5644 && [[theEvent window] isKindOfClass: [EmacsWindow class]]
5645 /* we must avoid an infinite loop here. */
5646 && (EmacsView *)[[theEvent window] delegate] != self)
5648 /* XXX: There is an occasional condition in which, when Emacs display
5649 updates a different frame from the current one, and temporarily
5650 selects it, then processes some interrupt-driven input
5651 (dispnew.c:3878), OS will send the event to the correct NSWindow, but
5652 for some reason that window has its first responder set to the NSView
5653 most recently updated (I guess), which is not the correct one. */
5654 [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
5658 if (nsEvArray == nil)
5659 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
5661 [NSCursor setHiddenUntilMouseMoves: YES];
5663 if (hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
5665 clear_mouse_face (hlinfo);
5666 hlinfo->mouse_face_hidden = 1;
5669 if (!processingCompose)
5671 /* When using screen sharing, no left or right information is sent,
5672 so use Left key in those cases. */
5673 int is_left_key, is_right_key;
5675 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
5676 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
5678 /* (Carbon way: [theEvent keyCode]) */
5680 /* is it a "function key"? */
5681 /* Note: Sometimes a plain key will have the NSNumericPadKeyMask
5682 flag set (this is probably a bug in the OS).
5684 if (code < 0x00ff && (flags&NSNumericPadKeyMask))
5686 fnKeysym = ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask);
5690 fnKeysym = ns_convert_key (code);
5695 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
5696 because Emacs treats Delete and KP-Delete same (in simple.el). */
5697 if ((fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33)
5698 #ifdef NS_IMPL_GNUSTEP
5699 /* GNUstep uses incompatible keycodes, even for those that are
5700 supposed to be hardware independent. Just check for delete.
5701 Keypad delete does not have keysym 0xFFFF.
5702 See http://savannah.gnu.org/bugs/?25395
5704 || (fnKeysym == 0xFFFF && code == 127)
5707 code = 0xFF08; /* backspace */
5712 /* are there modifiers? */
5713 emacs_event->modifiers = 0;
5715 if (flags & NSHelpKeyMask)
5716 emacs_event->modifiers |= hyper_modifier;
5718 if (flags & NSShiftKeyMask)
5719 emacs_event->modifiers |= shift_modifier;
5721 is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask;
5722 is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
5723 || (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask);
5726 emacs_event->modifiers |= parse_solitary_modifier
5727 (EQ (ns_right_command_modifier, Qleft)
5728 ? ns_command_modifier
5729 : ns_right_command_modifier);
5733 emacs_event->modifiers |= parse_solitary_modifier
5734 (ns_command_modifier);
5736 /* if super (default), take input manager's word so things like
5737 dvorak / qwerty layout work */
5738 if (EQ (ns_command_modifier, Qsuper)
5740 && [[theEvent characters] length] != 0)
5742 /* XXX: the code we get will be unshifted, so if we have
5743 a shift modifier, must convert ourselves */
5744 if (!(flags & NSShiftKeyMask))
5745 code = [[theEvent characters] characterAtIndex: 0];
5747 /* this is ugly and also requires linking w/Carbon framework
5748 (for LMGetKbdType) so for now leave this rare (?) case
5749 undealt with.. in future look into CGEvent methods */
5752 long smv = GetScriptManagerVariable (smKeyScript);
5753 Handle uchrHandle = GetResource
5754 ('uchr', GetScriptVariable (smv, smScriptKeys));
5756 UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle,
5757 [[theEvent characters] characterAtIndex: 0],
5758 kUCKeyActionDisplay,
5759 (flags & ~NSCommandKeyMask) >> 8,
5760 LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask,
5761 &dummy, 1, &dummy, &code);
5768 is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask;
5769 is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask
5770 || (! is_right_key && (flags & NSControlKeyMask) == NSControlKeyMask);
5773 emacs_event->modifiers |= parse_solitary_modifier
5774 (EQ (ns_right_control_modifier, Qleft)
5775 ? ns_control_modifier
5776 : ns_right_control_modifier);
5779 emacs_event->modifiers |= parse_solitary_modifier
5780 (ns_control_modifier);
5782 if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
5783 emacs_event->modifiers |=
5784 parse_solitary_modifier (ns_function_modifier);
5786 left_is_none = NILP (ns_alternate_modifier)
5787 || EQ (ns_alternate_modifier, Qnone);
5789 is_right_key = (flags & NSRightAlternateKeyMask)
5790 == NSRightAlternateKeyMask;
5791 is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
5793 && (flags & NSAlternateKeyMask) == NSAlternateKeyMask);
5797 if ((NILP (ns_right_alternate_modifier)
5798 || EQ (ns_right_alternate_modifier, Qnone)
5799 || (EQ (ns_right_alternate_modifier, Qleft) && left_is_none))
5801 { /* accept pre-interp alt comb */
5802 if ([[theEvent characters] length] > 0)
5803 code = [[theEvent characters] characterAtIndex: 0];
5804 /*HACK: clear lone shift modifier to stop next if from firing */
5805 if (emacs_event->modifiers == shift_modifier)
5806 emacs_event->modifiers = 0;
5809 emacs_event->modifiers |= parse_solitary_modifier
5810 (EQ (ns_right_alternate_modifier, Qleft)
5811 ? ns_alternate_modifier
5812 : ns_right_alternate_modifier);
5815 if (is_left_key) /* default = meta */
5817 if (left_is_none && !fnKeysym)
5818 { /* accept pre-interp alt comb */
5819 if ([[theEvent characters] length] > 0)
5820 code = [[theEvent characters] characterAtIndex: 0];
5821 /*HACK: clear lone shift modifier to stop next if from firing */
5822 if (emacs_event->modifiers == shift_modifier)
5823 emacs_event->modifiers = 0;
5826 emacs_event->modifiers |=
5827 parse_solitary_modifier (ns_alternate_modifier);
5831 fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",
5832 code, fnKeysym, flags, emacs_event->modifiers);
5834 /* if it was a function key or had modifiers, pass it directly to emacs */
5835 if (fnKeysym || (emacs_event->modifiers
5836 && (emacs_event->modifiers != shift_modifier)
5837 && [[theEvent charactersIgnoringModifiers] length] > 0))
5838 /*[[theEvent characters] length] */
5840 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5842 code |= (1<<28)|(3<<16);
5843 else if (code == 0x7f)
5844 code |= (1<<28)|(3<<16);
5846 emacs_event->kind = code > 0xFF
5847 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5849 emacs_event->code = code;
5850 EV_TRAILER (theEvent);
5851 processingCompose = NO;
5857 if (NS_KEYLOG && !processingCompose)
5858 fprintf (stderr, "keyDown: Begin compose sequence.\n");
5860 processingCompose = YES;
5861 [nsEvArray addObject: theEvent];
5862 [self interpretKeyEvents: nsEvArray];
5863 [nsEvArray removeObject: theEvent];
5867 #ifdef NS_IMPL_COCOA
5868 /* Needed to pick up Ctrl-tab and possibly other events that OS X has
5869 decided not to send key-down for.
5870 See http://osdir.com/ml/editors.vim.mac/2007-10/msg00141.html
5871 This only applies on Tiger and earlier.
5872 If it matches one of these, send it on to keyDown. */
5873 -(void)keyUp: (NSEvent *)theEvent
5875 int flags = [theEvent modifierFlags];
5876 int code = [theEvent keyCode];
5878 NSTRACE ("[EmacsView keyUp:]");
5880 if (floor (NSAppKitVersionNumber) <= 824 /*NSAppKitVersionNumber10_4*/ &&
5881 code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask))
5884 fprintf (stderr, "keyUp: passed test");
5885 ns_fake_keydown = YES;
5886 [self keyDown: theEvent];
5892 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
5895 /* <NSTextInput>: called when done composing;
5896 NOTE: also called when we delete over working text, followed immed.
5897 by doCommandBySelector: deleteBackward: */
5898 - (void)insertText: (id)aString
5901 int len = [(NSString *)aString length];
5904 NSTRACE ("[EmacsView insertText:]");
5907 NSLog (@"insertText '%@'\tlen = %d", aString, len);
5908 processingCompose = NO;
5913 /* first, clear any working text */
5914 if (workingText != nil)
5915 [self deleteWorkingText];
5917 /* now insert the string as keystrokes */
5918 for (i =0; i<len; i++)
5920 code = [aString characterAtIndex: i];
5921 /* TODO: still need this? */
5923 code = '~'; /* 0x7E */
5924 if (code != 32) /* Space */
5925 emacs_event->modifiers = 0;
5927 = code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
5928 emacs_event->code = code;
5929 EV_TRAILER ((id)nil);
5934 /* <NSTextInput>: inserts display of composing characters */
5935 - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
5937 NSString *str = [aString respondsToSelector: @selector (string)] ?
5938 [aString string] : aString;
5940 NSTRACE ("[EmacsView setMarkedText:selectedRange:]");
5943 NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu",
5944 str, (unsigned long)[str length],
5945 (unsigned long)selRange.length,
5946 (unsigned long)selRange.location);
5948 if (workingText != nil)
5949 [self deleteWorkingText];
5950 if ([str length] == 0)
5956 processingCompose = YES;
5957 workingText = [str copy];
5958 ns_working_text = build_string ([workingText UTF8String]);
5960 emacs_event->kind = NS_TEXT_EVENT;
5961 emacs_event->code = KEY_NS_PUT_WORKING_TEXT;
5962 EV_TRAILER ((id)nil);
5966 /* delete display of composing characters [not in <NSTextInput>] */
5967 - (void)deleteWorkingText
5969 NSTRACE ("[EmacsView deleteWorkingText]");
5971 if (workingText == nil)
5974 NSLog(@"deleteWorkingText len =%lu\n", (unsigned long)[workingText length]);
5975 [workingText release];
5977 processingCompose = NO;
5982 emacs_event->kind = NS_TEXT_EVENT;
5983 emacs_event->code = KEY_NS_UNPUT_WORKING_TEXT;
5984 EV_TRAILER ((id)nil);
5988 - (BOOL)hasMarkedText
5990 NSTRACE ("[EmacsView hasMarkedText]");
5992 return workingText != nil;
5996 - (NSRange)markedRange
5998 NSTRACE ("[EmacsView markedRange]");
6000 NSRange rng = workingText != nil
6001 ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
6003 NSLog (@"markedRange request");
6010 NSTRACE ("[EmacsView unmarkText]");
6013 NSLog (@"unmark (accept) text");
6014 [self deleteWorkingText];
6015 processingCompose = NO;
6019 /* used to position char selection windows, etc. */
6020 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
6024 struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
6026 NSTRACE ("[EmacsView firstRectForCharacterRange:]");
6029 NSLog (@"firstRectForCharRange request");
6031 rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
6032 rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
6033 pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x);
6034 pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y
6035 +FRAME_LINE_HEIGHT (emacsframe));
6037 pt = [self convertPoint: pt toView: nil];
6038 pt = [[self window] convertBaseToScreen: pt];
6044 - (NSInteger)conversationIdentifier
6046 return (NSInteger)self;
6050 - (void)doCommandBySelector: (SEL)aSelector
6052 NSTRACE ("[EmacsView doCommandBySelector:]");
6055 NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
6057 processingCompose = NO;
6058 if (aSelector == @selector (deleteBackward:))
6060 /* happens when user backspaces over an ongoing composition:
6061 throw a 'delete' into the event queue */
6064 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
6065 emacs_event->code = 0xFF08;
6066 EV_TRAILER ((id)nil);
6070 - (NSArray *)validAttributesForMarkedText
6072 static NSArray *arr = nil;
6073 if (arr == nil) arr = [NSArray new];
6074 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
6078 - (NSRange)selectedRange
6081 NSLog (@"selectedRange request");
6082 return NSMakeRange (NSNotFound, 0);
6085 #if defined (NS_IMPL_COCOA) || GNUSTEP_GUI_MAJOR_VERSION > 0 || \
6086 GNUSTEP_GUI_MINOR_VERSION > 22
6087 - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
6089 - (unsigned int)characterIndexForPoint: (NSPoint)thePoint
6093 NSLog (@"characterIndexForPoint request");
6097 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
6099 static NSAttributedString *str = nil;
6100 if (str == nil) str = [NSAttributedString new];
6102 NSLog (@"attributedSubstringFromRange request");
6106 /* End <NSTextInput> impl. */
6107 /*****************************************************************************/
6110 /* This is what happens when the user presses a mouse button. */
6111 - (void)mouseDown: (NSEvent *)theEvent
6113 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6114 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
6116 NSTRACE ("[EmacsView mouseDown:]");
6118 [self deleteWorkingText];
6123 dpyinfo->last_mouse_frame = emacsframe;
6124 /* appears to be needed to prevent spurious movement events generated on
6126 emacsframe->mouse_moved = 0;
6128 if ([theEvent type] == NSScrollWheel)
6130 CGFloat delta = [theEvent deltaY];
6131 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
6134 delta = [theEvent deltaX];
6137 NSTRACE_MSG ("deltaIsZero");
6140 emacs_event->kind = HORIZ_WHEEL_EVENT;
6143 emacs_event->kind = WHEEL_EVENT;
6145 emacs_event->code = 0;
6146 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
6147 ((delta > 0) ? up_modifier : down_modifier);
6151 emacs_event->kind = MOUSE_CLICK_EVENT;
6152 emacs_event->code = EV_BUTTON (theEvent);
6153 emacs_event->modifiers = EV_MODIFIERS (theEvent)
6154 | EV_UDMODIFIERS (theEvent);
6156 XSETINT (emacs_event->x, lrint (p.x));
6157 XSETINT (emacs_event->y, lrint (p.y));
6158 EV_TRAILER (theEvent);
6162 - (void)rightMouseDown: (NSEvent *)theEvent
6164 NSTRACE ("[EmacsView rightMouseDown:]");
6165 [self mouseDown: theEvent];
6169 - (void)otherMouseDown: (NSEvent *)theEvent
6171 NSTRACE ("[EmacsView otherMouseDown:]");
6172 [self mouseDown: theEvent];
6176 - (void)mouseUp: (NSEvent *)theEvent
6178 NSTRACE ("[EmacsView mouseUp:]");
6179 [self mouseDown: theEvent];
6183 - (void)rightMouseUp: (NSEvent *)theEvent
6185 NSTRACE ("[EmacsView rightMouseUp:]");
6186 [self mouseDown: theEvent];
6190 - (void)otherMouseUp: (NSEvent *)theEvent
6192 NSTRACE ("[EmacsView otherMouseUp:]");
6193 [self mouseDown: theEvent];
6197 - (void) scrollWheel: (NSEvent *)theEvent
6199 NSTRACE ("[EmacsView scrollWheel:]");
6200 [self mouseDown: theEvent];
6204 /* Tell emacs the mouse has moved. */
6205 - (void)mouseMoved: (NSEvent *)e
6207 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
6208 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6212 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]");
6214 dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e);
6215 pt = [self convertPoint: [e locationInWindow] fromView: nil];
6216 dpyinfo->last_mouse_motion_x = pt.x;
6217 dpyinfo->last_mouse_motion_y = pt.y;
6219 /* update any mouse face */
6220 if (hlinfo->mouse_face_hidden)
6222 hlinfo->mouse_face_hidden = 0;
6223 clear_mouse_face (hlinfo);
6226 /* tooltip handling */
6227 previous_help_echo_string = help_echo_string;
6228 help_echo_string = Qnil;
6230 if (!NILP (Vmouse_autoselect_window))
6232 NSTRACE_MSG ("mouse_autoselect_window");
6233 static Lisp_Object last_mouse_window;
6235 = window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0);
6237 if (WINDOWP (window)
6238 && !EQ (window, last_mouse_window)
6239 && !EQ (window, selected_window)
6240 && (focus_follows_mouse
6241 || (EQ (XWINDOW (window)->frame,
6242 XWINDOW (selected_window)->frame))))
6244 NSTRACE_MSG ("in_window");
6245 emacs_event->kind = SELECT_WINDOW_EVENT;
6246 emacs_event->frame_or_window = window;
6249 /* Remember the last window where we saw the mouse. */
6250 last_mouse_window = window;
6253 if (!note_mouse_movement (emacsframe, pt.x, pt.y))
6254 help_echo_string = previous_help_echo_string;
6256 XSETFRAME (frame, emacsframe);
6257 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
6259 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
6260 (note_mouse_highlight), which is called through the
6261 note_mouse_movement () call above */
6262 any_help_event_p = YES;
6263 gen_help_event (help_echo_string, frame, help_echo_window,
6264 help_echo_object, help_echo_pos);
6267 if (emacsframe->mouse_moved && send_appdefined)
6268 ns_send_appdefined (-1);
6272 - (void)mouseDragged: (NSEvent *)e
6274 NSTRACE ("[EmacsView mouseDragged:]");
6275 [self mouseMoved: e];
6279 - (void)rightMouseDragged: (NSEvent *)e
6281 NSTRACE ("[EmacsView rightMouseDragged:]");
6282 [self mouseMoved: e];
6286 - (void)otherMouseDragged: (NSEvent *)e
6288 NSTRACE ("[EmacsView otherMouseDragged:]");
6289 [self mouseMoved: e];
6293 - (BOOL)windowShouldClose: (id)sender
6295 NSEvent *e =[[self window] currentEvent];
6297 NSTRACE ("[EmacsView windowShouldClose:]");
6298 windowClosing = YES;
6301 emacs_event->kind = DELETE_WINDOW_EVENT;
6302 emacs_event->modifiers = 0;
6303 emacs_event->code = 0;
6305 /* Don't close this window, let this be done from lisp code. */
6309 - (void) updateFrameSize: (BOOL) delay;
6311 NSWindow *window = [self window];
6312 NSRect wr = [window frame];
6314 int oldc = cols, oldr = rows;
6315 int oldw = FRAME_PIXEL_WIDTH (emacsframe);
6316 int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
6319 NSTRACE ("[EmacsView updateFrameSize:]");
6320 NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
6321 NSTRACE_RECT ("Original frame", wr);
6322 NSTRACE_MSG ("Original columns: %d", cols);
6323 NSTRACE_MSG ("Original rows: %d", rows);
6325 if (! [self isFullscreen])
6327 #ifdef NS_IMPL_GNUSTEP
6328 // GNUstep does not always update the tool bar height. Force it.
6329 if (toolbar && [toolbar isVisible])
6330 update_frame_tool_bar (emacsframe);
6333 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
6334 + FRAME_TOOLBAR_HEIGHT (emacsframe);
6337 if (wait_for_tool_bar)
6339 if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0)
6341 NSTRACE_MSG ("Waiting for toolbar");
6344 wait_for_tool_bar = NO;
6347 neww = (int)wr.size.width - emacsframe->border_width;
6348 newh = (int)wr.size.height - extra;
6350 NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
6351 NSTRACE_MSG ("tool_bar_height: %d", emacsframe->tool_bar_height);
6353 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww);
6354 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh);
6356 if (cols < MINWIDTH)
6359 if (rows < MINHEIGHT)
6362 NSTRACE_MSG ("New columns: %d", cols);
6363 NSTRACE_MSG ("New rows: %d", rows);
6365 if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
6367 NSView *view = FRAME_NS_VIEW (emacsframe);
6369 change_frame_size (emacsframe,
6370 FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
6371 FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
6373 SET_FRAME_GARBAGED (emacsframe);
6374 cancel_mouse_face (emacsframe);
6376 wr = NSMakeRect (0, 0, neww, newh);
6378 [view setFrame: wr];
6380 // to do: consider using [NSNotificationCenter postNotificationName:].
6381 [self windowDidMove: // Update top/left.
6382 [NSNotification notificationWithName:NSWindowDidMoveNotification
6383 object:[view window]]];
6387 NSTRACE_MSG ("No change");
6391 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
6392 /* normalize frame to gridded text size */
6396 NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]",
6397 NSTRACE_ARG_SIZE (frameSize));
6398 NSTRACE_RECT ("[sender frame]", [sender frame]);
6399 NSTRACE_FSTYPE ("fs_state", fs_state);
6401 if (fs_state == FULLSCREEN_MAXIMIZED
6402 && (maximized_width != (int)frameSize.width
6403 || maximized_height != (int)frameSize.height))
6404 [self setFSValue: FULLSCREEN_NONE];
6405 else if (fs_state == FULLSCREEN_WIDTH
6406 && maximized_width != (int)frameSize.width)
6407 [self setFSValue: FULLSCREEN_NONE];
6408 else if (fs_state == FULLSCREEN_HEIGHT
6409 && maximized_height != (int)frameSize.height)
6410 [self setFSValue: FULLSCREEN_NONE];
6412 if (fs_state == FULLSCREEN_NONE)
6413 maximized_width = maximized_height = -1;
6415 if (! [self isFullscreen])
6417 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
6418 + FRAME_TOOLBAR_HEIGHT (emacsframe);
6421 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, frameSize.width);
6422 if (cols < MINWIDTH)
6425 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe,
6426 frameSize.height - extra);
6427 if (rows < MINHEIGHT)
6429 #ifdef NS_IMPL_COCOA
6431 /* this sets window title to have size in it; the wm does this under GS */
6432 NSRect r = [[self window] frame];
6433 if (r.size.height == frameSize.height && r.size.width == frameSize.width)
6441 else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize)
6444 NSWindow *window = [self window];
6447 char *t = strdup ([[[self window] title] UTF8String]);
6448 char *pos = strstr (t, " — ");
6453 size_title = xmalloc (strlen (old_title) + 40);
6454 esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
6455 [window setTitle: [NSString stringWithUTF8String: size_title]];
6460 #endif /* NS_IMPL_COCOA */
6462 NSTRACE_MSG ("cols: %d rows: %d", cols, rows);
6464 /* Restrict the new size to the text gird.
6466 Don't restrict the width if the user only adjusted the height, and
6467 vice versa. (Without this, the frame would shrink, and move
6468 slightly, if the window was resized by dragging one of its
6470 if (!frame_resize_pixelwise)
6472 NSRect r = [[self window] frame];
6474 if (r.size.width != frameSize.width)
6477 FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols);
6480 if (r.size.height != frameSize.height)
6483 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows) + extra;
6487 NSTRACE_RETURN_SIZE (frameSize);
6493 - (void)windowDidResize: (NSNotification *)notification
6495 NSTRACE ("[EmacsView windowDidResize:]");
6496 if (!FRAME_LIVE_P (emacsframe))
6498 NSTRACE_MSG ("Ignored (frame dead)");
6501 if (emacsframe->output_data.ns->in_animation)
6503 NSTRACE_MSG ("Ignored (in animation)");
6507 if (! [self fsIsNative])
6509 NSWindow *theWindow = [notification object];
6510 /* We can get notification on the non-FS window when in
6512 if ([self window] != theWindow) return;
6515 NSTRACE_RECT ("frame", [[notification object] frame]);
6517 #ifdef NS_IMPL_GNUSTEP
6518 NSWindow *theWindow = [notification object];
6520 /* In GNUstep, at least currently, it's possible to get a didResize
6521 without getting a willResize.. therefore we need to act as if we got
6522 the willResize now */
6523 NSSize sz = [theWindow frame].size;
6524 sz = [self windowWillResize: theWindow toSize: sz];
6525 #endif /* NS_IMPL_GNUSTEP */
6527 if (cols > 0 && rows > 0)
6529 [self updateFrameSize: YES];
6532 ns_send_appdefined (-1);
6535 #ifdef NS_IMPL_COCOA
6536 - (void)viewDidEndLiveResize
6538 NSTRACE ("[EmacsView viewDidEndLiveResize]");
6540 [super viewDidEndLiveResize];
6543 [[self window] setTitle: [NSString stringWithUTF8String: old_title]];
6547 maximizing_resize = NO;
6549 #endif /* NS_IMPL_COCOA */
6552 - (void)windowDidBecomeKey: (NSNotification *)notification
6553 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
6555 [self windowDidBecomeKey];
6559 - (void)windowDidBecomeKey /* for direct calls */
6561 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6562 struct frame *old_focus = dpyinfo->x_focus_frame;
6564 NSTRACE ("[EmacsView windowDidBecomeKey]");
6566 if (emacsframe != old_focus)
6567 dpyinfo->x_focus_frame = emacsframe;
6569 ns_frame_rehighlight (emacsframe);
6573 emacs_event->kind = FOCUS_IN_EVENT;
6574 EV_TRAILER ((id)nil);
6579 - (void)windowDidResignKey: (NSNotification *)notification
6580 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
6582 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
6583 BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe;
6584 NSTRACE ("[EmacsView windowDidResignKey:]");
6587 dpyinfo->x_focus_frame = 0;
6589 emacsframe->mouse_moved = 0;
6590 ns_frame_rehighlight (emacsframe);
6592 /* FIXME: for some reason needed on second and subsequent clicks away
6593 from sole-frame Emacs to get hollow box to show */
6594 if (!windowClosing && [[self window] isVisible] == YES)
6596 x_update_cursor (emacsframe, 1);
6597 x_set_frame_alpha (emacsframe);
6600 if (any_help_event_p)
6603 XSETFRAME (frame, emacsframe);
6604 help_echo_string = Qnil;
6605 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
6608 if (emacs_event && is_focus_frame)
6610 [self deleteWorkingText];
6611 emacs_event->kind = FOCUS_OUT_EVENT;
6612 EV_TRAILER ((id)nil);
6617 - (void)windowWillMiniaturize: sender
6619 NSTRACE ("[EmacsView windowWillMiniaturize:]");
6623 - (void)setFrame:(NSRect)frameRect;
6625 NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]",
6626 NSTRACE_ARG_RECT (frameRect));
6628 [super setFrame:(NSRect)frameRect];
6644 - initFrameFromEmacs: (struct frame *)f
6652 NSTRACE ("[EmacsView initFrameFromEmacs:]");
6653 NSTRACE_MSG ("cols:%d lines:%d\n", f->text_cols, f->text_lines);
6656 processingCompose = NO;
6657 scrollbarsNeedingUpdate = 0;
6658 fs_state = FULLSCREEN_NONE;
6659 fs_before_fs = next_maximized = -1;
6660 #ifdef HAVE_NATIVE_FS
6661 fs_is_native = ns_use_native_fullscreen;
6665 maximized_width = maximized_height = -1;
6668 ns_userRect = NSMakeRect (0, 0, 0, 0);
6669 r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
6670 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
6671 [self initWithFrame: r];
6672 [self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
6674 FRAME_NS_VIEW (f) = self;
6676 #ifdef NS_IMPL_COCOA
6678 maximizing_resize = NO;
6681 win = [[EmacsWindow alloc]
6682 initWithContentRect: r
6683 styleMask: (NSResizableWindowMask |
6684 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
6685 NSTitledWindowMask |
6687 NSMiniaturizableWindowMask |
6688 NSClosableWindowMask)
6689 backing: NSBackingStoreBuffered
6692 #ifdef HAVE_NATIVE_FS
6693 [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
6697 bwidth = f->border_width = wr.size.width - r.size.width;
6698 tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
6700 [win setAcceptsMouseMovedEvents: YES];
6701 [win setDelegate: self];
6702 #if !defined (NS_IMPL_COCOA) || \
6703 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
6704 [win useOptimizedDrawing: YES];
6707 [[win contentView] addSubview: self];
6710 [self registerForDraggedTypes: ns_drag_types];
6713 name = [NSString stringWithUTF8String:
6714 NILP (tem) ? "Emacs" : SSDATA (tem)];
6715 [win setTitle: name];
6717 /* toolbar support */
6718 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
6719 [NSString stringWithFormat: @"Emacs Frame %d",
6721 [win setToolbar: toolbar];
6722 [toolbar setVisible: NO];
6724 /* Don't set frame garbaged until tool bar is up to date?
6725 This avoids an extra clear and redraw (flicker) at frame creation. */
6726 if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES;
6727 else wait_for_tool_bar = NO;
6730 #ifdef NS_IMPL_COCOA
6732 NSButton *toggleButton;
6733 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
6734 [toggleButton setTarget: self];
6735 [toggleButton setAction: @selector (toggleToolbar: )];
6738 FRAME_TOOLBAR_HEIGHT (f) = 0;
6742 [win setMiniwindowTitle:
6743 [NSString stringWithUTF8String: SSDATA (tem)]];
6746 NSScreen *screen = [win screen];
6750 NSPoint pt = NSMakePoint
6751 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
6752 IN_BOUND (-SCREENMAX,
6753 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX));
6755 [win setFrameTopLeftPoint: pt];
6757 NSTRACE_RECT ("new frame", [win frame]);
6761 [win makeFirstResponder: self];
6763 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
6764 (FRAME_DEFAULT_FACE (emacsframe)), emacsframe);
6765 [win setBackgroundColor: col];
6766 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
6767 [win setOpaque: NO];
6769 #if !defined (NS_IMPL_COCOA) || \
6770 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
6771 [self allocateGState];
6773 [NSApp registerServicesMenuSendTypes: ns_send_types
6781 - (void)windowDidMove: sender
6783 NSWindow *win = [self window];
6784 NSRect r = [win frame];
6785 NSArray *screens = [NSScreen screens];
6786 NSScreen *screen = [screens objectAtIndex: 0];
6788 NSTRACE ("[EmacsView windowDidMove:]");
6790 if (!emacsframe->output_data.ns)
6794 emacsframe->left_pos = r.origin.x;
6795 emacsframe->top_pos =
6796 [screen frame].size.height - (r.origin.y + r.size.height);
6801 /* Called AFTER method below, but before our windowWillResize call there leads
6802 to windowDidResize -> x_set_window_size. Update emacs' notion of frame
6803 location so set_window_size moves the frame. */
6804 - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
6806 NSTRACE (("[EmacsView windowShouldZoom:toFrame:" NSTRACE_FMT_RECT "]"
6807 NSTRACE_FMT_RETURN "YES"),
6808 NSTRACE_ARG_RECT (newFrame));
6810 emacsframe->output_data.ns->zooming = 1;
6815 /* Override to do something slightly nonstandard, but nice. First click on
6816 zoom button will zoom vertically. Second will zoom completely. Third
6817 returns to original. */
6818 - (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
6819 defaultFrame:(NSRect)defaultFrame
6821 // TODO: Rename to "currentFrame" and assign "result" properly in
6823 NSRect result = [sender frame];
6825 NSTRACE (("[EmacsView windowWillUseStandardFrame:defaultFrame:"
6826 NSTRACE_FMT_RECT "]"),
6827 NSTRACE_ARG_RECT (defaultFrame));
6828 NSTRACE_FSTYPE ("fs_state", fs_state);
6829 NSTRACE_FSTYPE ("fs_before_fs", fs_before_fs);
6830 NSTRACE_FSTYPE ("next_maximized", next_maximized);
6831 NSTRACE_RECT ("ns_userRect", ns_userRect);
6832 NSTRACE_RECT ("[sender frame]", [sender frame]);
6834 if (fs_before_fs != -1) /* Entering fullscreen */
6836 NSTRACE_MSG ("Entering fullscreen");
6837 result = defaultFrame;
6841 // Save the window size and position (frame) before the resize.
6842 if (fs_state != FULLSCREEN_MAXIMIZED
6843 && fs_state != FULLSCREEN_WIDTH)
6845 ns_userRect.size.width = result.size.width;
6846 ns_userRect.origin.x = result.origin.x;
6849 if (fs_state != FULLSCREEN_MAXIMIZED
6850 && fs_state != FULLSCREEN_HEIGHT)
6852 ns_userRect.size.height = result.size.height;
6853 ns_userRect.origin.y = result.origin.y;
6856 NSTRACE_RECT ("ns_userRect (2)", ns_userRect);
6858 if (next_maximized == FULLSCREEN_HEIGHT
6859 || (next_maximized == -1
6860 && abs ((int)(defaultFrame.size.height - result.size.height))
6861 > FRAME_LINE_HEIGHT (emacsframe)))
6864 NSTRACE_MSG ("FULLSCREEN_HEIGHT");
6865 maximized_height = result.size.height = defaultFrame.size.height;
6866 maximized_width = -1;
6867 result.origin.y = defaultFrame.origin.y;
6868 if (ns_userRect.size.height != 0)
6870 result.origin.x = ns_userRect.origin.x;
6871 result.size.width = ns_userRect.size.width;
6873 [self setFSValue: FULLSCREEN_HEIGHT];
6874 #ifdef NS_IMPL_COCOA
6875 maximizing_resize = YES;
6878 else if (next_maximized == FULLSCREEN_WIDTH)
6880 NSTRACE_MSG ("FULLSCREEN_WIDTH");
6881 maximized_width = result.size.width = defaultFrame.size.width;
6882 maximized_height = -1;
6883 result.origin.x = defaultFrame.origin.x;
6884 if (ns_userRect.size.width != 0)
6886 result.origin.y = ns_userRect.origin.y;
6887 result.size.height = ns_userRect.size.height;
6889 [self setFSValue: FULLSCREEN_WIDTH];
6891 else if (next_maximized == FULLSCREEN_MAXIMIZED
6892 || (next_maximized == -1
6893 && abs ((int)(defaultFrame.size.width - result.size.width))
6894 > FRAME_COLUMN_WIDTH (emacsframe)))
6896 NSTRACE_MSG ("FULLSCREEN_MAXIMIZED");
6898 result = defaultFrame; /* second click */
6899 maximized_width = result.size.width;
6900 maximized_height = result.size.height;
6901 [self setFSValue: FULLSCREEN_MAXIMIZED];
6902 #ifdef NS_IMPL_COCOA
6903 maximizing_resize = YES;
6909 NSTRACE_MSG ("Restore");
6910 result = ns_userRect.size.height ? ns_userRect : result;
6911 NSTRACE_RECT ("restore (2)", result);
6912 ns_userRect = NSMakeRect (0, 0, 0, 0);
6913 #ifdef NS_IMPL_COCOA
6914 maximizing_resize = fs_state != FULLSCREEN_NONE;
6916 [self setFSValue: FULLSCREEN_NONE];
6917 maximized_width = maximized_height = -1;
6921 if (fs_before_fs == -1) next_maximized = -1;
6923 NSTRACE_RECT ("Final ns_userRect", ns_userRect);
6924 NSTRACE_MSG ("Final maximized_width: %d", maximized_width);
6925 NSTRACE_MSG ("Final maximized_height: %d", maximized_height);
6926 NSTRACE_FSTYPE ("Final next_maximized", next_maximized);
6928 [self windowWillResize: sender toSize: result.size];
6930 NSTRACE_RETURN_RECT (result);
6936 - (void)windowDidDeminiaturize: sender
6938 NSTRACE ("[EmacsView windowDidDeminiaturize:]");
6939 if (!emacsframe->output_data.ns)
6942 SET_FRAME_ICONIFIED (emacsframe, 0);
6943 SET_FRAME_VISIBLE (emacsframe, 1);
6944 windows_or_buffers_changed = 63;
6948 emacs_event->kind = DEICONIFY_EVENT;
6949 EV_TRAILER ((id)nil);
6954 - (void)windowDidExpose: sender
6956 NSTRACE ("[EmacsView windowDidExpose:]");
6957 if (!emacsframe->output_data.ns)
6960 SET_FRAME_VISIBLE (emacsframe, 1);
6961 SET_FRAME_GARBAGED (emacsframe);
6963 if (send_appdefined)
6964 ns_send_appdefined (-1);
6968 - (void)windowDidMiniaturize: sender
6970 NSTRACE ("[EmacsView windowDidMiniaturize:]");
6971 if (!emacsframe->output_data.ns)
6974 SET_FRAME_ICONIFIED (emacsframe, 1);
6975 SET_FRAME_VISIBLE (emacsframe, 0);
6979 emacs_event->kind = ICONIFY_EVENT;
6980 EV_TRAILER ((id)nil);
6984 #ifdef HAVE_NATIVE_FS
6985 - (NSApplicationPresentationOptions)window:(NSWindow *)window
6986 willUseFullScreenPresentationOptions:
6987 (NSApplicationPresentationOptions)proposedOptions
6989 return proposedOptions|NSApplicationPresentationAutoHideToolbar;
6993 - (void)windowWillEnterFullScreen:(NSNotification *)notification
6995 NSTRACE ("[EmacsView windowWillEnterFullScreen:]");
6996 [self windowWillEnterFullScreen];
6998 - (void)windowWillEnterFullScreen /* provided for direct calls */
7000 NSTRACE ("[EmacsView windowWillEnterFullScreen]");
7001 fs_before_fs = fs_state;
7004 - (void)windowDidEnterFullScreen:(NSNotification *)notification
7006 NSTRACE ("[EmacsView windowDidEnterFullScreen:]");
7007 [self windowDidEnterFullScreen];
7010 - (void)windowDidEnterFullScreen /* provided for direct calls */
7012 NSTRACE ("[EmacsView windowDidEnterFullScreen]");
7013 [self setFSValue: FULLSCREEN_BOTH];
7014 if (! [self fsIsNative])
7016 [self windowDidBecomeKey];
7017 [nonfs_window orderOut:self];
7021 BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (emacsframe) ? YES : NO;
7022 #ifdef NS_IMPL_COCOA
7023 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
7024 unsigned val = (unsigned)[NSApp presentationOptions];
7026 // OSX 10.7 bug fix, the menu won't appear without this.
7027 // val is non-zero on other OSX versions.
7030 NSApplicationPresentationOptions options
7031 = NSApplicationPresentationAutoHideDock
7032 | NSApplicationPresentationAutoHideMenuBar
7033 | NSApplicationPresentationFullScreen
7034 | NSApplicationPresentationAutoHideToolbar;
7036 [NSApp setPresentationOptions: options];
7040 [toolbar setVisible:tbar_visible];
7044 - (void)windowWillExitFullScreen:(NSNotification *)notification
7046 NSTRACE ("[EmacsView windowWillExitFullScreen:]");
7047 [self windowWillExitFullScreen];
7050 - (void)windowWillExitFullScreen /* provided for direct calls */
7052 NSTRACE ("[EmacsView windowWillExitFullScreen]");
7053 if (!FRAME_LIVE_P (emacsframe))
7055 NSTRACE_MSG ("Ignored (frame dead)");
7058 if (next_maximized != -1)
7059 fs_before_fs = next_maximized;
7062 - (void)windowDidExitFullScreen:(NSNotification *)notification
7064 NSTRACE ("[EmacsView windowDidExitFullScreen:]");
7065 [self windowDidExitFullScreen];
7068 - (void)windowDidExitFullScreen /* provided for direct calls */
7070 NSTRACE ("[EmacsView windowDidExitFullScreen]");
7071 if (!FRAME_LIVE_P (emacsframe))
7073 NSTRACE_MSG ("Ignored (frame dead)");
7076 [self setFSValue: fs_before_fs];
7078 #ifdef HAVE_NATIVE_FS
7079 [self updateCollectionBehavior];
7081 if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
7083 [toolbar setVisible:YES];
7084 update_frame_tool_bar (emacsframe);
7085 [self updateFrameSize:YES];
7086 [[self window] display];
7089 [toolbar setVisible:NO];
7091 if (next_maximized != -1)
7092 [[self window] performZoom:self];
7097 return fs_is_native;
7100 - (BOOL)isFullscreen
7102 NSTRACE ("[EmacsView isFullscreen]");
7104 if (! fs_is_native) return nonfs_window != nil;
7105 #ifdef HAVE_NATIVE_FS
7106 return ([[self window] styleMask] & NSFullScreenWindowMask) != 0;
7112 #ifdef HAVE_NATIVE_FS
7113 - (void)updateCollectionBehavior
7115 NSTRACE ("[EmacsView updateCollectionBehavior]");
7117 if (! [self isFullscreen])
7119 NSWindow *win = [self window];
7120 NSWindowCollectionBehavior b = [win collectionBehavior];
7121 if (ns_use_native_fullscreen)
7122 b |= NSWindowCollectionBehaviorFullScreenPrimary;
7124 b &= ~NSWindowCollectionBehaviorFullScreenPrimary;
7126 [win setCollectionBehavior: b];
7127 fs_is_native = ns_use_native_fullscreen;
7132 - (void)toggleFullScreen: (id)sender
7140 NSTRACE ("[EmacsView toggleFullScreen:]");
7144 #ifdef HAVE_NATIVE_FS
7145 [[self window] toggleFullScreen:sender];
7151 onFirstScreen = [[w screen] isEqual:[[NSScreen screens] objectAtIndex:0]];
7154 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
7155 (FRAME_DEFAULT_FACE (f)),
7158 if (fs_state != FULLSCREEN_BOTH)
7160 NSScreen *screen = [w screen];
7162 #if defined (NS_IMPL_COCOA) && \
7163 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
7164 /* Hide ghost menu bar on secondary monitor? */
7165 if (! onFirstScreen)
7166 onFirstScreen = [NSScreen screensHaveSeparateSpaces];
7168 /* Hide dock and menubar if we are on the primary screen. */
7171 #ifdef NS_IMPL_COCOA
7172 NSApplicationPresentationOptions options
7173 = NSApplicationPresentationAutoHideDock
7174 | NSApplicationPresentationAutoHideMenuBar;
7176 [NSApp setPresentationOptions: options];
7178 [NSMenu setMenuBarVisible:NO];
7182 fw = [[EmacsFSWindow alloc]
7183 initWithContentRect:[w contentRectForFrameRect:wr]
7184 styleMask:NSBorderlessWindowMask
7185 backing:NSBackingStoreBuffered
7189 [fw setContentView:[w contentView]];
7190 [fw setTitle:[w title]];
7191 [fw setDelegate:self];
7192 [fw setAcceptsMouseMovedEvents: YES];
7193 #if !defined (NS_IMPL_COCOA) || \
7194 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
7195 [fw useOptimizedDrawing: YES];
7197 [fw setBackgroundColor: col];
7198 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
7201 f->border_width = 0;
7202 FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
7203 tobar_height = FRAME_TOOLBAR_HEIGHT (f);
7204 FRAME_TOOLBAR_HEIGHT (f) = 0;
7208 [self windowWillEnterFullScreen];
7209 [fw makeKeyAndOrderFront:NSApp];
7210 [fw makeFirstResponder:self];
7212 r = [fw frameRectForContentRect:[screen frame]];
7213 [fw setFrame: r display:YES animate:ns_use_fullscreen_animation];
7214 [self windowDidEnterFullScreen];
7225 #ifdef NS_IMPL_COCOA
7226 [NSApp setPresentationOptions: NSApplicationPresentationDefault];
7228 [NSMenu setMenuBarVisible:YES];
7232 [w setContentView:[fw contentView]];
7233 [w setBackgroundColor: col];
7234 if ([col alphaComponent] != (EmacsCGFloat) 1.0)
7237 f->border_width = bwidth;
7238 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
7239 if (FRAME_EXTERNAL_TOOL_BAR (f))
7240 FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
7242 // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications.
7244 [self windowWillExitFullScreen];
7245 [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
7247 [w makeKeyAndOrderFront:NSApp];
7248 [self windowDidExitFullScreen];
7249 [self updateFrameSize:YES];
7255 NSTRACE ("[EmacsView handleFS]");
7257 if (fs_state != emacsframe->want_fullscreen)
7259 if (fs_state == FULLSCREEN_BOTH)
7261 NSTRACE_MSG ("fs_state == FULLSCREEN_BOTH");
7262 [self toggleFullScreen:self];
7265 switch (emacsframe->want_fullscreen)
7267 case FULLSCREEN_BOTH:
7268 NSTRACE_MSG ("FULLSCREEN_BOTH");
7269 [self toggleFullScreen:self];
7271 case FULLSCREEN_WIDTH:
7272 NSTRACE_MSG ("FULLSCREEN_WIDTH");
7273 next_maximized = FULLSCREEN_WIDTH;
7274 if (fs_state != FULLSCREEN_BOTH)
7275 [[self window] performZoom:self];
7277 case FULLSCREEN_HEIGHT:
7278 NSTRACE_MSG ("FULLSCREEN_HEIGHT");
7279 next_maximized = FULLSCREEN_HEIGHT;
7280 if (fs_state != FULLSCREEN_BOTH)
7281 [[self window] performZoom:self];
7283 case FULLSCREEN_MAXIMIZED:
7284 NSTRACE_MSG ("FULLSCREEN_MAXIMIZED");
7285 next_maximized = FULLSCREEN_MAXIMIZED;
7286 if (fs_state != FULLSCREEN_BOTH)
7287 [[self window] performZoom:self];
7289 case FULLSCREEN_NONE:
7290 NSTRACE_MSG ("FULLSCREEN_NONE");
7291 if (fs_state != FULLSCREEN_BOTH)
7293 next_maximized = FULLSCREEN_NONE;
7294 [[self window] performZoom:self];
7299 emacsframe->want_fullscreen = FULLSCREEN_NONE;
7304 - (void) setFSValue: (int)value
7306 NSTRACE ("[EmacsView setFSValue:" NSTRACE_FMT_FSTYPE "]",
7307 NSTRACE_ARG_FSTYPE(value));
7309 Lisp_Object lval = Qnil;
7312 case FULLSCREEN_BOTH:
7315 case FULLSCREEN_WIDTH:
7318 case FULLSCREEN_HEIGHT:
7321 case FULLSCREEN_MAXIMIZED:
7325 store_frame_param (emacsframe, Qfullscreen, lval);
7329 - (void)mouseEntered: (NSEvent *)theEvent
7331 NSTRACE ("[EmacsView mouseEntered:]");
7333 FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
7334 = EV_TIMESTAMP (theEvent);
7338 - (void)mouseExited: (NSEvent *)theEvent
7340 Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL;
7342 NSTRACE ("[EmacsView mouseExited:]");
7347 FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
7348 = EV_TIMESTAMP (theEvent);
7350 if (emacsframe == hlinfo->mouse_face_mouse_frame)
7352 clear_mouse_face (hlinfo);
7353 hlinfo->mouse_face_mouse_frame = 0;
7360 NSTRACE ("[EmacsView menuDown:]");
7361 if (context_menu_value == -1)
7362 context_menu_value = [sender tag];
7365 NSInteger tag = [sender tag];
7366 find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
7367 emacsframe->menu_bar_vector,
7371 ns_send_appdefined (-1);
7376 - (EmacsToolbar *)toolbar
7382 /* this gets called on toolbar button click */
7383 - toolbarClicked: (id)item
7386 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
7388 NSTRACE ("[EmacsView toolbarClicked:]");
7393 /* send first event (for some reason two needed) */
7394 theEvent = [[self window] currentEvent];
7395 emacs_event->kind = TOOL_BAR_EVENT;
7396 XSETFRAME (emacs_event->arg, emacsframe);
7397 EV_TRAILER (theEvent);
7399 emacs_event->kind = TOOL_BAR_EVENT;
7400 /* XSETINT (emacs_event->code, 0); */
7401 emacs_event->arg = AREF (emacsframe->tool_bar_items,
7402 idx + TOOL_BAR_ITEM_KEY);
7403 emacs_event->modifiers = EV_MODIFIERS (theEvent);
7404 EV_TRAILER (theEvent);
7409 - toggleToolbar: (id)sender
7411 NSTRACE ("[EmacsView toggleToolbar:]");
7416 emacs_event->kind = NS_NONKEY_EVENT;
7417 emacs_event->code = KEY_NS_TOGGLE_TOOLBAR;
7418 EV_TRAILER ((id)nil);
7423 - (void)drawRect: (NSRect)rect
7425 int x = NSMinX (rect), y = NSMinY (rect);
7426 int width = NSWidth (rect), height = NSHeight (rect);
7428 NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]",
7429 NSTRACE_ARG_RECT(rect));
7431 if (!emacsframe || !emacsframe->output_data.ns)
7434 ns_clear_frame_area (emacsframe, x, y, width, height);
7436 expose_frame (emacsframe, x, y, width, height);
7440 drawRect: may be called (at least in OS X 10.5) for invisible
7441 views as well for some reason. Thus, do not infer visibility
7444 emacsframe->async_visible = 1;
7445 emacsframe->async_iconified = 0;
7450 /* NSDraggingDestination protocol methods. Actually this is not really a
7451 protocol, but a category of Object. O well... */
7453 -(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
7455 NSTRACE ("[EmacsView draggingEntered:]");
7456 return NSDragOperationGeneric;
7460 -(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
7466 -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
7471 NSEvent *theEvent = [[self window] currentEvent];
7473 NSDragOperation op = [sender draggingSourceOperationMask];
7476 NSTRACE ("[EmacsView performDragOperation:]");
7481 position = [self convertPoint: [sender draggingLocation] fromView: nil];
7482 x = lrint (position.x); y = lrint (position.y);
7484 pb = [sender draggingPasteboard];
7485 type = [pb availableTypeFromArray: ns_drag_types];
7487 if (! (op & (NSDragOperationMove|NSDragOperationDelete)) &&
7488 // URL drags contain all operations (0xf), don't allow all to be set.
7491 if (op & NSDragOperationLink)
7492 modifiers |= NSControlKeyMask;
7493 if (op & NSDragOperationCopy)
7494 modifiers |= NSAlternateKeyMask;
7495 if (op & NSDragOperationGeneric)
7496 modifiers |= NSCommandKeyMask;
7499 modifiers = EV_MODIFIERS2 (modifiers);
7504 else if ([type isEqualToString: NSFilenamesPboardType])
7507 NSEnumerator *fenum;
7510 if (!(files = [pb propertyListForType: type]))
7513 fenum = [files objectEnumerator];
7514 while ( (file = [fenum nextObject]) )
7516 emacs_event->kind = DRAG_N_DROP_EVENT;
7517 XSETINT (emacs_event->x, x);
7518 XSETINT (emacs_event->y, y);
7519 ns_input_file = append2 (ns_input_file,
7520 build_string ([file UTF8String]));
7521 emacs_event->modifiers = modifiers;
7522 emacs_event->arg = list2 (Qfile, build_string ([file UTF8String]));
7523 EV_TRAILER (theEvent);
7527 else if ([type isEqualToString: NSURLPboardType])
7529 NSURL *url = [NSURL URLFromPasteboard: pb];
7530 if (url == nil) return NO;
7532 emacs_event->kind = DRAG_N_DROP_EVENT;
7533 XSETINT (emacs_event->x, x);
7534 XSETINT (emacs_event->y, y);
7535 emacs_event->modifiers = modifiers;
7536 emacs_event->arg = list2 (Qurl,
7537 build_string ([[url absoluteString]
7539 EV_TRAILER (theEvent);
7541 if ([url isFileURL] != NO)
7543 NSString *file = [url path];
7544 ns_input_file = append2 (ns_input_file,
7545 build_string ([file UTF8String]));
7549 else if ([type isEqualToString: NSStringPboardType]
7550 || [type isEqualToString: NSTabularTextPboardType])
7554 if (! (data = [pb stringForType: type]))
7557 emacs_event->kind = DRAG_N_DROP_EVENT;
7558 XSETINT (emacs_event->x, x);
7559 XSETINT (emacs_event->y, y);
7560 emacs_event->modifiers = modifiers;
7561 emacs_event->arg = list2 (Qnil, build_string ([data UTF8String]));
7562 EV_TRAILER (theEvent);
7567 fprintf (stderr, "Invalid data type in dragging pasteboard");
7573 - (id) validRequestorForSendType: (NSString *)typeSent
7574 returnType: (NSString *)typeReturned
7576 NSTRACE ("[EmacsView validRequestorForSendType:returnType:]");
7577 if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound
7578 && typeReturned == nil)
7580 if (! NILP (ns_get_local_selection (QPRIMARY, QUTF8_STRING)))
7584 return [super validRequestorForSendType: typeSent
7585 returnType: typeReturned];
7589 /* The next two methods are part of NSServicesRequests informal protocol,
7590 supposedly called when a services menu item is chosen from this app.
7591 But this should not happen because we override the services menu with our
7592 own entries which call ns-perform-service.
7593 Nonetheless, it appeared to happen (under strange circumstances): bug#1435.
7594 So let's at least stub them out until further investigation can be done. */
7596 - (BOOL) readSelectionFromPasteboard: (NSPasteboard *)pb
7598 /* we could call ns_string_from_pasteboard(pboard) here but then it should
7599 be written into the buffer in place of the existing selection..
7600 ordinary service calls go through functions defined in ns-win.el */
7604 - (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types
7606 NSArray *typesDeclared;
7609 NSTRACE ("[EmacsView writeSelectionToPasteboard:types:]");
7611 /* We only support NSStringPboardType */
7612 if ([types containsObject:NSStringPboardType] == NO) {
7616 val = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
7617 if (CONSP (val) && SYMBOLP (XCAR (val)))
7620 if (CONSP (val) && NILP (XCDR (val)))
7623 if (! STRINGP (val))
7626 typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
7627 [pb declareTypes:typesDeclared owner:nil];
7628 ns_string_to_pasteboard (pb, val);
7633 /* setMini =YES means set from internal (gives a finder icon), NO means set nil
7634 (gives a miniaturized version of the window); currently we use the latter for
7635 frames whose active buffer doesn't correspond to any file
7636 (e.g., '*scratch*') */
7637 - setMiniwindowImage: (BOOL) setMini
7639 id image = [[self window] miniwindowImage];
7640 NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini);
7642 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
7643 about "AppleDockIconEnabled" notwithstanding, however the set message
7644 below has its effect nonetheless. */
7645 if (image != emacsframe->output_data.ns->miniimage)
7647 if (image && [image isKindOfClass: [EmacsImage class]])
7649 [[self window] setMiniwindowImage:
7650 setMini ? emacsframe->output_data.ns->miniimage : nil];
7657 - (void) setRows: (int) r andColumns: (int) c
7659 NSTRACE ("[EmacsView setRows:%d andColumns:%d]", r, c);
7664 - (int) fullscreenState
7669 @end /* EmacsView */
7673 /* ==========================================================================
7675 EmacsWindow implementation
7677 ========================================================================== */
7679 @implementation EmacsWindow
7681 #ifdef NS_IMPL_COCOA
7682 - (id)accessibilityAttributeValue:(NSString *)attribute
7684 Lisp_Object str = Qnil;
7685 struct frame *f = SELECTED_FRAME ();
7686 struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contents);
7688 NSTRACE ("[EmacsWindow accessibilityAttributeValue:]");
7690 if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
7691 return NSAccessibilityTextFieldRole;
7693 if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]
7694 && curbuf && ! NILP (BVAR (curbuf, mark_active)))
7696 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
7698 else if (curbuf && [attribute isEqualToString:NSAccessibilityValueAttribute])
7700 if (! NILP (BVAR (curbuf, mark_active)))
7701 str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
7705 ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf);
7706 ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte;
7707 ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf);
7709 if (! NILP (BVAR (curbuf, enable_multibyte_characters)))
7710 str = make_uninit_multibyte_string (range, byte_range);
7712 str = make_uninit_string (range);
7713 /* To check: This returns emacs-utf-8, which is a superset of utf-8.
7714 Is this a problem? */
7715 memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range);
7722 if (CONSP (str) && SYMBOLP (XCAR (str)))
7725 if (CONSP (str) && NILP (XCDR (str)))
7730 const char *utfStr = SSDATA (str);
7731 NSString *nsStr = [NSString stringWithUTF8String: utfStr];
7736 return [super accessibilityAttributeValue:attribute];
7738 #endif /* NS_IMPL_COCOA */
7740 /* Constrain size and placement of a frame.
7742 By returning the original "frameRect", the frame is not
7743 constrained. This can lead to unwanted situations where, for
7744 example, the menu bar covers the frame.
7746 The default implementation (accessed using "super") constrains the
7747 frame to the visible area of SCREEN, minus the menu bar (if
7748 present) and the Dock. Note that default implementation also calls
7749 windowWillResize, with the frame it thinks should have. (This can
7750 make the frame exit maximized mode.)
7752 Note that this should work in situations where multiple monitors
7753 are present. Common configurations are side-by-side monitors and a
7754 monitor on top of another (e.g. when a laptop is placed under a
7756 - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
7758 NSTRACE ("[EmacsWindow constrainFrameRect:" NSTRACE_FMT_RECT " toScreen:]",
7759 NSTRACE_ARG_RECT (frameRect));
7761 #ifdef NS_IMPL_COCOA
7762 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
7763 // If separate spaces is on, it is like each screen is independent. There is
7764 // no spanning of frames across screens.
7765 if ([NSScreen screensHaveSeparateSpaces])
7767 NSTRACE_MSG ("Screens have separate spaces");
7768 frameRect = [super constrainFrameRect:frameRect toScreen:screen];
7769 NSTRACE_RETURN_RECT (frameRect);
7775 return constrain_frame_rect(frameRect);
7779 - (void)performZoom:(id)sender
7781 NSTRACE ("[EmacsWindow performZoom:]");
7783 return [super performZoom:sender];
7786 - (void)zoom:(id)sender
7788 NSTRACE ("[EmacsWindow zoom:]");
7790 ns_update_auto_hide_menu_bar();
7792 // Below are three zoom implementations. In the final commit, the
7793 // idea is that the last should be included.
7796 // Native zoom done using the standard zoom animation. Size of the
7797 // resulting frame reduced to accommodate the Dock and, if present,
7799 [super zoom:sender];
7802 // Native zoom done using the standard zoom animation, plus an
7803 // explicit resize to cover the full screen.
7804 [super zoom:sender];
7806 // After the native zoom, resize the resulting frame to fill the
7807 // entire screen, except the menu-bar.
7809 // This works for all practical purposes. (The only minor oddity is
7810 // when transiting from full-height frame to a maximized, the
7811 // animation reduces the height of the frame slightly (to the 4
7812 // pixels needed to accommodate the Doc) before it snaps back into
7813 // full height. The user would need a very trained eye to spot
7815 NSScreen * screen = [self screen];
7818 int fs_state = [(EmacsView *)[self delegate] fullscreenState];
7820 NSTRACE_FSTYPE ("fullscreenState", fs_state);
7822 NSRect sr = [screen frame];
7823 NSRect wr = [self frame];
7824 NSTRACE_RECT ("Rect after zoom", wr);
7828 if (fs_state == FULLSCREEN_MAXIMIZED
7829 || fs_state == FULLSCREEN_HEIGHT)
7832 newWr.size.height = sr.size.height - ns_menu_bar_height(screen);
7835 if (fs_state == FULLSCREEN_MAXIMIZED
7836 || fs_state == FULLSCREEN_WIDTH)
7839 newWr.size.width = sr.size.width;
7842 if (newWr.size.width != wr.size.width
7843 || newWr.size.height != wr.size.height
7844 || newWr.origin.x != wr.origin.x
7845 || newWr.origin.y != wr.origin.y)
7847 NSTRACE_MSG ("New frame different");
7848 [self setFrame: newWr display: NO];
7852 // Non-native zoom which is done instantaneously. The resulting frame
7853 // covers the entire screen, except the menu-bar, if present.
7854 NSScreen * screen = [self screen];
7857 NSRect sr = [screen frame];
7858 sr.size.height -= ns_menu_bar_height (screen);
7860 sr = [[self delegate] windowWillUseStandardFrame:self
7862 [self setFrame: sr display: NO];
7867 - (void)setFrame:(NSRect)windowFrame
7868 display:(BOOL)displayViews
7870 NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT " display:%d]",
7871 NSTRACE_ARG_RECT (windowFrame), displayViews);
7873 [super setFrame:windowFrame display:displayViews];
7876 - (void)setFrame:(NSRect)windowFrame
7877 display:(BOOL)displayViews
7878 animate:(BOOL)performAnimation
7880 NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT
7881 " display:%d performAnimation:%d]",
7882 NSTRACE_ARG_RECT (windowFrame), displayViews, performAnimation);
7884 [super setFrame:windowFrame display:displayViews animate:performAnimation];
7887 - (void)setFrameTopLeftPoint:(NSPoint)point
7889 NSTRACE ("[EmacsWindow setFrameTopLeftPoint:" NSTRACE_FMT_POINT "]",
7890 NSTRACE_ARG_POINT (point));
7892 [super setFrameTopLeftPoint:point];
7894 @end /* EmacsWindow */
7897 @implementation EmacsFSWindow
7899 - (BOOL)canBecomeKeyWindow
7904 - (BOOL)canBecomeMainWindow
7911 /* ==========================================================================
7913 EmacsScroller implementation
7915 ========================================================================== */
7918 @implementation EmacsScroller
7920 /* for repeat button push */
7921 #define SCROLL_BAR_FIRST_DELAY 0.5
7922 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
7924 + (CGFloat) scrollerWidth
7926 /* TODO: if we want to allow variable widths, this is the place to do it,
7927 however neither GNUstep nor Cocoa support it very well */
7929 #if !defined (NS_IMPL_COCOA) || \
7930 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
7931 r = [NSScroller scrollerWidth];
7933 r = [NSScroller scrollerWidthForControlSize: NSRegularControlSize
7934 scrollerStyle: NSScrollerStyleLegacy];
7940 - initFrame: (NSRect )r window: (Lisp_Object)nwin
7942 NSTRACE ("[EmacsScroller initFrame: window:]");
7944 r.size.width = [EmacsScroller scrollerWidth];
7945 [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
7946 [self setContinuous: YES];
7947 [self setEnabled: YES];
7949 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
7950 locked against the top and bottom edges, and right edge on OS X, where
7951 scrollers are on right. */
7952 #ifdef NS_IMPL_GNUSTEP
7953 [self setAutoresizingMask: NSViewMaxXMargin | NSViewHeightSizable];
7955 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
7958 window = XWINDOW (nwin);
7960 pixel_height = NSHeight (r);
7961 if (pixel_height == 0) pixel_height = 1;
7962 min_portion = 20 / pixel_height;
7964 frame = XFRAME (window->frame);
7965 if (FRAME_LIVE_P (frame))
7968 EmacsView *view = FRAME_NS_VIEW (frame);
7969 NSView *sview = [[view window] contentView];
7970 NSArray *subs = [sview subviews];
7972 /* disable optimization stopping redraw of other scrollbars */
7973 view->scrollbarsNeedingUpdate = 0;
7974 for (i =[subs count]-1; i >= 0; i--)
7975 if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]])
7976 view->scrollbarsNeedingUpdate++;
7977 [sview addSubview: self];
7980 /* [self setFrame: r]; */
7986 - (void)setFrame: (NSRect)newRect
7988 NSTRACE ("[EmacsScroller setFrame:]");
7990 /* block_input (); */
7991 pixel_height = NSHeight (newRect);
7992 if (pixel_height == 0) pixel_height = 1;
7993 min_portion = 20 / pixel_height;
7994 [super setFrame: newRect];
7995 /* unblock_input (); */
8001 NSTRACE ("[EmacsScroller dealloc]");
8003 wset_vertical_scroll_bar (window, Qnil);
8011 NSTRACE ("[EmacsScroller condemn]");
8019 NSTRACE ("[EmacsScroller reprieve]");
8027 NSTRACE ("[EmacsScroller judge]");
8028 bool ret = condemned;
8033 /* ensure other scrollbar updates after deletion */
8034 view = (EmacsView *)FRAME_NS_VIEW (frame);
8036 view->scrollbarsNeedingUpdate++;
8038 wset_vertical_scroll_bar (window, Qnil);
8040 [self removeFromSuperview];
8048 - (void)resetCursorRects
8050 NSRect visible = [self visibleRect];
8051 NSTRACE ("[EmacsScroller resetCursorRects]");
8053 if (!NSIsEmptyRect (visible))
8054 [self addCursorRect: visible cursor: [NSCursor arrowCursor]];
8055 [[NSCursor arrowCursor] setOnMouseEntered: YES];
8059 - (int) checkSamePosition: (int) position portion: (int) portion
8062 return em_position ==position && em_portion ==portion && em_whole ==whole
8063 && portion != whole; /* needed for resize empty buf */
8067 - setPosition: (int)position portion: (int)portion whole: (int)whole
8069 NSTRACE ("[EmacsScroller setPosition:portion:whole:]");
8071 em_position = position;
8072 em_portion = portion;
8075 if (portion >= whole)
8077 #ifdef NS_IMPL_COCOA
8078 [self setKnobProportion: 1.0];
8079 [self setDoubleValue: 1.0];
8081 [self setFloatValue: 0.0 knobProportion: 1.0];
8088 portion = max ((float)whole*min_portion/pixel_height, portion);
8089 pos = (float)position / (whole - portion);
8090 por = (CGFloat)portion/whole;
8091 #ifdef NS_IMPL_COCOA
8092 [self setKnobProportion: por];
8093 [self setDoubleValue: pos];
8095 [self setFloatValue: pos knobProportion: por];
8102 /* set up emacs_event */
8103 - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
8107 NSTRACE ("[EmacsScroller sendScrollEventAtLoc:fromEvent:]");
8112 emacs_event->part = last_hit_part;
8113 emacs_event->code = 0;
8114 emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier;
8115 XSETWINDOW (win, window);
8116 emacs_event->frame_or_window = win;
8117 emacs_event->timestamp = EV_TIMESTAMP (e);
8118 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
8119 emacs_event->arg = Qnil;
8120 XSETINT (emacs_event->x, loc * pixel_height);
8121 XSETINT (emacs_event->y, pixel_height-20);
8125 n_emacs_events_pending++;
8126 kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
8129 hold_event (emacs_event);
8130 EVENT_INIT (*emacs_event);
8131 ns_send_appdefined (-1);
8135 /* called manually thru timer to implement repeated button action w/hold-down */
8136 - repeatScroll: (NSTimer *)scrollEntry
8138 NSEvent *e = [[self window] currentEvent];
8139 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
8140 BOOL inKnob = [self testPart: p] == NSScrollerKnob;
8142 NSTRACE ("[EmacsScroller repeatScroll:]");
8144 /* clear timer if need be */
8145 if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
8147 [scroll_repeat_entry invalidate];
8148 [scroll_repeat_entry release];
8149 scroll_repeat_entry = nil;
8155 = [[NSTimer scheduledTimerWithTimeInterval:
8156 SCROLL_BAR_CONTINUOUS_DELAY
8158 selector: @selector (repeatScroll:)
8164 [self sendScrollEventAtLoc: 0 fromEvent: e];
8169 /* Asynchronous mouse tracking for scroller. This allows us to dispatch
8170 mouseDragged events without going into a modal loop. */
8171 - (void)mouseDown: (NSEvent *)e
8174 /* hitPart is only updated AFTER event is passed on */
8175 NSScrollerPart part = [self testPart: [e locationInWindow]];
8176 CGFloat inc = 0.0, loc, kloc, pos;
8179 NSTRACE ("[EmacsScroller mouseDown:]");
8183 case NSScrollerDecrementPage:
8184 last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
8185 case NSScrollerIncrementPage:
8186 last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
8187 case NSScrollerDecrementLine:
8188 last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
8189 case NSScrollerIncrementLine:
8190 last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
8191 case NSScrollerKnob:
8192 last_hit_part = scroll_bar_handle; break;
8193 case NSScrollerKnobSlot: /* GNUstep-only */
8194 last_hit_part = scroll_bar_move_ratio; break;
8195 default: /* NSScrollerNoPart? */
8196 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %ld\n",
8203 pos = 0; /* ignored */
8205 /* set a timer to repeat, as we can't let superclass do this modally */
8207 = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY
8209 selector: @selector (repeatScroll:)
8216 /* handle, or on GNUstep possibly slot */
8217 NSEvent *fake_event;
8219 /* compute float loc in slot and mouse offset on knob */
8220 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
8222 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
8228 else if (loc >= NSHeight (sr))
8230 loc = NSHeight (sr);
8238 kr = [self convertRect: [self rectForPart: NSScrollerKnob]
8240 kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
8242 last_mouse_offset = kloc;
8244 /* if knob, tell emacs a location offset by knob pos
8245 (to indicate top of handle) */
8246 if (part == NSScrollerKnob)
8247 pos = (loc - last_mouse_offset) / NSHeight (sr);
8249 /* else this is a slot click on GNUstep: go straight there */
8250 pos = loc / NSHeight (sr);
8252 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
8253 fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
8254 location: [e locationInWindow]
8255 modifierFlags: [e modifierFlags]
8256 timestamp: [e timestamp]
8257 windowNumber: [e windowNumber]
8258 context: [e context]
8259 eventNumber: [e eventNumber]
8260 clickCount: [e clickCount]
8261 pressure: [e pressure]];
8262 [super mouseUp: fake_event];
8265 if (part != NSScrollerKnob)
8266 [self sendScrollEventAtLoc: pos fromEvent: e];
8270 /* Called as we manually track scroller drags, rather than superclass. */
8271 - (void)mouseDragged: (NSEvent *)e
8276 NSTRACE ("[EmacsScroller mouseDragged:]");
8278 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
8280 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
8286 else if (loc >= NSHeight (sr) + last_mouse_offset)
8288 loc = NSHeight (sr) + last_mouse_offset;
8291 pos = (loc - last_mouse_offset) / NSHeight (sr);
8292 [self sendScrollEventAtLoc: pos fromEvent: e];
8296 - (void)mouseUp: (NSEvent *)e
8298 NSTRACE ("[EmacsScroller mouseUp:]");
8300 if (scroll_repeat_entry)
8302 [scroll_repeat_entry invalidate];
8303 [scroll_repeat_entry release];
8304 scroll_repeat_entry = nil;
8306 last_hit_part = scroll_bar_above_handle;
8310 /* treat scrollwheel events in the bar as though they were in the main window */
8311 - (void) scrollWheel: (NSEvent *)theEvent
8313 NSTRACE ("[EmacsScroller scrollWheel:]");
8315 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
8316 [view mouseDown: theEvent];
8319 @end /* EmacsScroller */
8322 #ifdef NS_IMPL_GNUSTEP
8323 /* Dummy class to get rid of startup warnings. */
8324 @implementation EmacsDocument
8330 /* ==========================================================================
8332 Font-related functions; these used to be in nsfaces.m
8334 ========================================================================== */
8338 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
8340 struct font *font = XFONT_OBJECT (font_object);
8341 EmacsView *view = FRAME_NS_VIEW (f);
8342 int font_ascent, font_descent;
8345 fontset = fontset_from_font (font_object);
8346 FRAME_FONTSET (f) = fontset;
8348 if (FRAME_FONT (f) == font)
8349 /* This font is already set in frame F. There's nothing more to
8353 FRAME_FONT (f) = font;
8355 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
8356 FRAME_COLUMN_WIDTH (f) = font->average_width;
8357 get_font_ascent_descent (font, &font_ascent, &font_descent);
8358 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
8360 /* Compute the scroll bar width in character columns. */
8361 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
8363 int wid = FRAME_COLUMN_WIDTH (f);
8364 FRAME_CONFIG_SCROLL_BAR_COLS (f)
8365 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
8369 int wid = FRAME_COLUMN_WIDTH (f);
8370 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
8373 /* Compute the scroll bar height in character lines. */
8374 if (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0)
8376 int height = FRAME_LINE_HEIGHT (f);
8377 FRAME_CONFIG_SCROLL_BAR_LINES (f)
8378 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
8382 int height = FRAME_LINE_HEIGHT (f);
8383 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
8386 /* Now make the frame display the given font. */
8387 if (FRAME_NS_WINDOW (f) != 0 && ! [view isFullscreen])
8388 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
8389 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
8396 /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
8397 /* Note: ns_font_to_xlfd and ns_fontname_to_xlfd no longer needed, removed
8401 ns_xlfd_to_fontname (const char *xlfd)
8402 /* --------------------------------------------------------------------------
8403 Convert an X font name (XLFD) to an NS font name.
8404 Only family is used.
8405 The string returned is temporarily allocated.
8406 -------------------------------------------------------------------------- */
8408 char *name = xmalloc (180);
8412 if (!strncmp (xlfd, "--", 2))
8413 sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
8415 sscanf (xlfd, "-%*[^-]-%[^-]179-", name);
8417 /* stopgap for malformed XLFD input */
8418 if (strlen (name) == 0)
8419 strcpy (name, "Monaco");
8421 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
8422 also uppercase after '-' or ' ' */
8423 name[0] = c_toupper (name[0]);
8424 for (len =strlen (name), i =0; i<len; i++)
8430 name[i+1] = c_toupper (name[i+1]);
8432 else if (name[i] == '_')
8436 name[i+1] = c_toupper (name[i+1]);
8439 /*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
8440 ret = [[NSString stringWithUTF8String: name] UTF8String];
8447 syms_of_nsterm (void)
8449 NSTRACE ("syms_of_nsterm");
8451 ns_antialias_threshold = 10.0;
8453 /* from 23+ we need to tell emacs what modifiers there are.. */
8454 DEFSYM (Qmodifier_value, "modifier-value");
8455 DEFSYM (Qalt, "alt");
8456 DEFSYM (Qhyper, "hyper");
8457 DEFSYM (Qmeta, "meta");
8458 DEFSYM (Qsuper, "super");
8459 DEFSYM (Qcontrol, "control");
8460 DEFSYM (QUTF8_STRING, "UTF8_STRING");
8462 DEFSYM (Qfile, "file");
8463 DEFSYM (Qurl, "url");
8465 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
8466 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
8467 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
8468 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
8469 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
8471 DEFVAR_LISP ("ns-input-file", ns_input_file,
8472 "The file specified in the last NS event.");
8473 ns_input_file =Qnil;
8475 DEFVAR_LISP ("ns-working-text", ns_working_text,
8476 "String for visualizing working composition sequence.");
8477 ns_working_text =Qnil;
8479 DEFVAR_LISP ("ns-input-font", ns_input_font,
8480 "The font specified in the last NS event.");
8481 ns_input_font =Qnil;
8483 DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize,
8484 "The fontsize specified in the last NS event.");
8485 ns_input_fontsize =Qnil;
8487 DEFVAR_LISP ("ns-input-line", ns_input_line,
8488 "The line specified in the last NS event.");
8489 ns_input_line =Qnil;
8491 DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
8492 "The service name specified in the last NS event.");
8493 ns_input_spi_name =Qnil;
8495 DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg,
8496 "The service argument specified in the last NS event.");
8497 ns_input_spi_arg =Qnil;
8499 DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier,
8500 "This variable describes the behavior of the alternate or option key.\n\
8501 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8502 Set to none means that the alternate / option key is not interpreted by Emacs\n\
8503 at all, allowing it to be used at a lower level for accented character entry.");
8504 ns_alternate_modifier = Qmeta;
8506 DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier,
8507 "This variable describes the behavior of the right alternate or option key.\n\
8508 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8509 Set to left means be the same key as `ns-alternate-modifier'.\n\
8510 Set to none means that the alternate / option key is not interpreted by Emacs\n\
8511 at all, allowing it to be used at a lower level for accented character entry.");
8512 ns_right_alternate_modifier = Qleft;
8514 DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
8515 "This variable describes the behavior of the command key.\n\
8516 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
8517 ns_command_modifier = Qsuper;
8519 DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
8520 "This variable describes the behavior of the right command key.\n\
8521 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8522 Set to left means be the same key as `ns-command-modifier'.\n\
8523 Set to none means that the command / option key is not interpreted by Emacs\n\
8524 at all, allowing it to be used at a lower level for accented character entry.");
8525 ns_right_command_modifier = Qleft;
8527 DEFVAR_LISP ("ns-control-modifier", ns_control_modifier,
8528 "This variable describes the behavior of the control key.\n\
8529 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
8530 ns_control_modifier = Qcontrol;
8532 DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier,
8533 "This variable describes the behavior of the right control key.\n\
8534 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8535 Set to left means be the same key as `ns-control-modifier'.\n\
8536 Set to none means that the control / option key is not interpreted by Emacs\n\
8537 at all, allowing it to be used at a lower level for accented character entry.");
8538 ns_right_control_modifier = Qleft;
8540 DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
8541 "This variable describes the behavior of the function key (on laptops).\n\
8542 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
8543 Set to none means that the function key is not interpreted by Emacs at all,\n\
8544 allowing it to be used at a lower level for accented character entry.");
8545 ns_function_modifier = Qnone;
8547 DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
8548 "Non-nil (the default) means to render text antialiased.");
8549 ns_antialias_text = Qt;
8551 DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
8552 "Whether to confirm application quit using dialog.");
8553 ns_confirm_quit = Qnil;
8555 DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
8556 doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
8557 Only works on OSX 10.6 or later. */);
8558 ns_auto_hide_menu_bar = Qnil;
8560 DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen,
8561 doc: /*Non-nil means to use native fullscreen on OSX >= 10.7.
8562 Nil means use fullscreen the old (< 10.7) way. The old way works better with
8563 multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7.
8564 Default is t for OSX >= 10.7, nil otherwise. */);
8565 #ifdef HAVE_NATIVE_FS
8566 ns_use_native_fullscreen = YES;
8568 ns_use_native_fullscreen = NO;
8570 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
8572 DEFVAR_BOOL ("ns-use-fullscreen-animation", ns_use_fullscreen_animation,
8573 doc: /*Non-nil means use animation on non-native fullscreen.
8574 For native fullscreen, this does nothing.
8575 Default is nil. */);
8576 ns_use_fullscreen_animation = NO;
8578 DEFVAR_BOOL ("ns-use-srgb-colorspace", ns_use_srgb_colorspace,
8579 doc: /*Non-nil means to use sRGB colorspace on OSX >= 10.7.
8580 Note that this does not apply to images.
8581 This variable is ignored on OSX < 10.7 and GNUstep. */);
8582 ns_use_srgb_colorspace = YES;
8584 /* TODO: move to common code */
8585 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
8586 doc: /* Which toolkit scroll bars Emacs uses, if any.
8587 A value of nil means Emacs doesn't use toolkit scroll bars.
8588 With the X Window system, the value is a symbol describing the
8589 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
8590 With MS Windows or Nextstep, the value is t. */);
8591 Vx_toolkit_scroll_bars = Qt;
8593 DEFVAR_BOOL ("x-use-underline-position-properties",
8594 x_use_underline_position_properties,
8595 doc: /*Non-nil means make use of UNDERLINE_POSITION font properties.
8596 A value of nil means ignore them. If you encounter fonts with bogus
8597 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
8598 to 4.1, set this to nil. */);
8599 x_use_underline_position_properties = 0;
8601 DEFVAR_BOOL ("x-underline-at-descent-line",
8602 x_underline_at_descent_line,
8603 doc: /* Non-nil means to draw the underline at the same place as the descent line.
8604 A value of nil means to draw the underline according to the value of the
8605 variable `x-use-underline-position-properties', which is usually at the
8606 baseline level. The default value is nil. */);
8607 x_underline_at_descent_line = 0;
8609 /* Tell Emacs about this window system. */
8610 Fprovide (Qns, Qnil);
8612 DEFSYM (Qcocoa, "cocoa");
8613 DEFSYM (Qgnustep, "gnustep");
8615 #ifdef NS_IMPL_COCOA
8616 Fprovide (Qcocoa, Qnil);
8619 Fprovide (Qgnustep, Qnil);