GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
*/
+/* This should be the first include, as it may set up #defines affecting
+ interpretation of even the system includes. */
+#include "config.h"
+
#include <math.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-#include "config.h"
#include "lisp.h"
#include "blockinput.h"
#include "sysselect.h"
#define EV_UDMODIFIERS(e) \
((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
| (([e type] == NSRightMouseDown) ? down_modifier : 0) \
+ | (([e type] == NSOtherMouseDown) ? down_modifier : 0) \
| (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
| (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
+ | (([e type] == NSOtherMouseDragged) ? down_modifier : 0) \
| (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
- | (([e type] == NSRightMouseUp) ? up_modifier : 0))
+ | (([e type] == NSRightMouseUp) ? up_modifier : 0) \
+ | (([e type] == NSOtherMouseUp) ? up_modifier : 0))
#define EV_BUTTON(e) \
((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
- (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : 1)
+ (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : \
+ [e buttonNumber] - 1)
/* Convert the time field to a timestamp in milliseconds. */
#ifdef NS_IMPL_GNUSTEP
{
NSView *view = FRAME_NS_VIEW (f);
NSTRACE (ns_update_begin);
-/*fprintf (stderr, "\\%p\n", f); */
ns_updating_frame = f;
[view lockFocus];
the entire window.
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_focus);
+// NSTRACE (ns_focus);
#ifdef NS_IMPL_GNUSTEP
NSRect u;
if (n == 2)
Internal: Remove focus on given frame
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_unfocus);
+// NSTRACE (ns_unfocus);
if (gsaved)
{
r.origin.y += (r.size.height - dim.y) / 2;
r.size.width = dim.x;
r.size.height = dim.y;
- /* XXX: cacheImageInRect under GNUSTEP does not account for
+ /* XXX: cacheImageInRect under GNUstep does not account for
offset in x_set_window_size, so overestimate (4 fine on Cocoa) */
surr = NSInsetRect (r, -10, -10);
ns_focus (frame, &surr, 1);
if (dpyinfo->x_highlight_frame &&
dpyinfo->x_highlight_frame != old_highlight)
{
- /* as of 20080602 the lower and raise are superfluous */
if (old_highlight)
- {
- /*ns_lower_frame (old_highlight); */
+ {
x_update_cursor (old_highlight, 1);
- }
+ x_set_frame_alpha (old_highlight);
+ }
if (dpyinfo->x_highlight_frame)
- {
- /*ns_raise_frame (dpyinfo->x_highlight_frame); */
+ {
x_update_cursor (dpyinfo->x_highlight_frame, 1);
- }
+ x_set_frame_alpha (dpyinfo->x_highlight_frame);
+ }
}
}
pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-
+
/* If we have a change in toolbar display, calculate height */
if (tb)
/* XXX: GNUstep has not yet implemented the first method below, added
}
+
/* ==========================================================================
Color management
========================================================================== */
+
NSColor *
ns_lookup_indexed_color (unsigned long idx, struct frame *f)
{
color_table->size * sizeof (NSColor *));
}
idx = color_table->avail++;
- index = [NSNumber numberWithUnsignedInt: idx];
}
color_table->colors[idx] = color;
void
ns_free_indexed_color (unsigned long idx, struct frame *f)
{
- struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
+ struct ns_color_table *color_table;
NSColor *color;
- if (!idx)
+ NSNumber *index;
+
+ if (!f)
return;
+
+ color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
+
+ if (idx <= 0 || idx >= color_table->size) {
+ message1("ns_free_indexed_color: Color index out of range.\n");
+ return;
+ }
+
+ index = [NSNumber numberWithUnsignedInt: idx];
+ if ([color_table->empty_indices containsObject: index]) {
+ message1("ns_free_indexed_color: attempt to free already freed color.\n");
+ return;
+ }
+
color = color_table->colors[idx];
[color release];
color_table->colors[idx] = nil;
/* Direct colors (hex values) */
if (hex)
{
- unsigned int color = 0;
+ unsigned long color = 0;
if (sscanf (hex, "%x", &color))
{
- float f1 = ((color >> 24) & 0xff) / 255.0;
- float f2 = ((color >> 16) & 0xff) / 255.0;
- float f3 = ((color >> 8) & 0xff) / 255.0;
- float f4 = ((color ) & 0xff) / 255.0;
+ float f1, f2, f3, f4;
+ /* Assume it's either 1 byte or 2 per channel... */
+ if (strlen(hex) > 8) {
+ f1 = ((color >> 48) & 0xffff) / 65535.0;
+ f2 = ((color >> 32) & 0xffff) / 65535.0;
+ f3 = ((color >> 16) & 0xffff) / 65535.0;
+ f4 = ((color ) & 0xffff) / 65535.0;
+ } else {
+ f1 = ((color >> 24) & 0xff) / 255.0;
+ f2 = ((color >> 16) & 0xff) / 255.0;
+ f3 = ((color >> 8) & 0xff) / 255.0;
+ f4 = ((color ) & 0xff) / 255.0;
+ }
switch (color_space)
{
}
+void
+x_set_frame_alpha (struct frame *f)
+/* --------------------------------------------------------------------------
+ change the entire-frame transparency
+ -------------------------------------------------------------------------- */
+{
+ struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+ EmacsView *view = FRAME_NS_VIEW (f);
+ double alpha = 1.0;
+ double alpha_min = 1.0;
+
+ if (dpyinfo->x_highlight_frame == f)
+ alpha = f->alpha[0];
+ else
+ alpha = f->alpha[1];
+
+ if (FLOATP (Vframe_alpha_lower_limit))
+ alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
+ else if (INTEGERP (Vframe_alpha_lower_limit))
+ alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
+
+ if (alpha < 0.0)
+ return;
+ else if (1.0 < alpha)
+ alpha = 1.0;
+ else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
+ alpha = alpha_min;
+
+#ifdef NS_IMPL_COCOA
+ [[view window] setAlphaValue: alpha];
+#endif
+}
+
/* ==========================================================================
known as last_mouse_glyph.
------------------------------------------------------------------------ */
{
- NSTRACE (note_mouse_movement);
+// NSTRACE (note_mouse_movement);
XSETFRAME (last_mouse_motion_frame, frame);
-
+
/* Note, this doesn't get called for enter/leave, since we don't have a
position. Those are taken care of in the corresponding NSView methods. */
if (!view || !face)
return;
+ NSTRACE (ns_clear_frame_area);
+
r = NSIntersectionRect (r, [view frame]);
ns_focus (f, &r, 1);
[ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
int on_p, int active_p)
/* --------------------------------------------------------------------------
External call (RIF): draw cursor
- (modeled after x_draw_window_cursor and erase_phys_cursor.
- FIXME: erase_phys_cursor is called from display_and_set_cursor,
- called from update_window_cursor/x_update_window_end/...
- Why do we have to duplicate this code?
+ (modeled after x_draw_window_cursor
+ FIXME: cursor_width is effectively bogus -- it sometimes gets set
+ in xdisp.c set_frame_cursor_types, sometimes left uninitialized;
+ DON'T USE IT (no other terms do)
-------------------------------------------------------------------------- */
{
NSRect r, s;
int fx, fy, h;
struct frame *f = WINDOW_XFRAME (w);
struct glyph *phys_cursor_glyph;
- int overspill;
- char drawGlyph = 0, cursorType, oldCursorType;
- int new_cursor_type;
- int new_cursor_width;
- int active_cursor;
- enum draw_glyphs_face hl;
- struct glyph_matrix *active_glyphs = w->current_matrix;
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- int hpos = w->phys_cursor.hpos;
- int vpos = w->phys_cursor.vpos;
- struct glyph_row *cursor_row;
+ int overspill, cursorToDraw;
NSTRACE (dumpcursor);
+//fprintf(stderr, "drawcursor (%d,%d) activep = %d\tonp = %d\tc_type = %d\twidth = %d\n",x,y, active_p,on_p,cursor_type,cursor_width);
- if (!on_p) // check this? && !w->phys_cursor_on_p)
+ if (!on_p)
return;
w->phys_cursor_type = cursor_type;
if (cursor_type == NO_CURSOR)
{
- w->phys_cursor_on_p = 0;
w->phys_cursor_width = 0;
return;
}
if (overspill > 0)
r.size.width -= overspill;
- oldCursorType = FRAME_CURSOR (f);
- cursorType = FRAME_CURSOR (f) = FRAME_NEW_CURSOR (f);
- /* TODO: 23: use emacs stored cursor color instead of ns-specific */
- f->output_data.ns->current_cursor_color
- = f->output_data.ns->desired_cursor_color;
-
/* TODO: only needed in rare cases with last-resort font in HELLO..
should we do this more efficiently? */
- ns_clip_to_row (w, glyph_row, -1, NO);
-/* ns_focus (f, &r, 1); */
+ ns_clip_to_row (w, glyph_row, -1, NO); /* do ns_focus(f, &r, 1); if remove */
+ [FRAME_CURSOR_COLOR (f) set];
- /* Why would this be needed?
- if (FRAME_LAST_INACTIVE (f))
- {
- * previously hollow box; clear entire area *
- [FRAME_BACKGROUND_COLOR (f) set];
- NSRectFill (r);
- drawGlyph = 1;
- FRAME_LAST_INACTIVE (f) = NO;
- }
- */
+#ifdef NS_IMPL_COCOA
+ /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
+ atomic. Cleaner ways of doing this should be investigated.
+ One way would be to set a global variable DRAWING_CURSOR
+ when making the call to draw_phys..(), don't focus in that
+ case, then move the ns_unfocus() here after that call. */
+ NSDisableScreenUpdates ();
+#endif
- /* prepare to draw */
- if (cursorType == no_highlight || cursor_type == NO_CURSOR)
+ cursorToDraw = active_p ? cursor_type : HOLLOW_BOX_CURSOR;
+ switch (cursorToDraw)
{
- /* clearing for blink: erase the cursor itself */
-
- /* No cursor displayed or row invalidated => nothing to do on the
- screen. */
- if (w->phys_cursor_type == NO_CURSOR)
- return;
-
- /* VPOS >= active_glyphs->nrows means that window has been resized.
- Don't bother to erase the cursor. */
- if (vpos >= active_glyphs->nrows)
- return;
-
- /* If row containing cursor is marked invalid, there is nothing we
- can do. */
- cursor_row = MATRIX_ROW (active_glyphs, vpos);
- if (!cursor_row->enabled_p)
- return;
-
- /* If line spacing is > 0, old cursor may only be partially visible in
- window after split-window. So adjust visible height. */
- cursor_row->visible_height = min (cursor_row->visible_height,
- window_text_bottom_y (w) - cursor_row->y);
-
- /* If row is completely invisible, don't attempt to delete a cursor which
- isn't there. This can happen if cursor is at top of a window, and
- we switch to a buffer with a header line in that window. */
- if (cursor_row->visible_height <= 0)
- return;
-
- /* If cursor is in the fringe, erase by drawing actual bitmap there. */
- if (cursor_row->cursor_in_fringe_p)
- {
- cursor_row->cursor_in_fringe_p = 0;
- draw_fringe_bitmap (w, cursor_row, 0);
- return;
- }
-
- /* This can happen when the new row is shorter than the old one.
- In this case, either draw_glyphs or clear_end_of_line
- should have cleared the cursor. Note that we wouldn't be
- able to erase the cursor in this case because we don't have a
- cursor glyph at hand. */
- if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
- return;
-
- /* If the cursor is in the mouse face area, redisplay that when
- we clear the cursor. */
- if (! NILP (dpyinfo->mouse_face_window)
- && w == XWINDOW (dpyinfo->mouse_face_window)
- && (vpos > dpyinfo->mouse_face_beg_row
- || (vpos == dpyinfo->mouse_face_beg_row
- && hpos >= dpyinfo->mouse_face_beg_col))
- && (vpos < dpyinfo->mouse_face_end_row
- || (vpos == dpyinfo->mouse_face_end_row
- && hpos < dpyinfo->mouse_face_end_col))
- /* Don't redraw the cursor's spot in mouse face if it is at the
- end of a line (on a newline). The cursor appears there, but
- mouse highlighting does not. */
- && cursor_row->used[TEXT_AREA] > hpos)
- hl = DRAW_MOUSE_FACE;
- else
- hl = DRAW_NORMAL_TEXT;
- drawGlyph = 1; // just draw the Glyph
+ case NO_CURSOR:
+ break;
+ case FILLED_BOX_CURSOR:
+ NSRectFill (r);
+ break;
+ case HOLLOW_BOX_CURSOR:
+ NSRectFill (r);
[FRAME_BACKGROUND_COLOR (f) set];
-
-#ifdef NS_IMPL_COCOA
- NSDisableScreenUpdates ();
-#endif
- }
- else
- {
- cursorType = cursor_type;
- hl = DRAW_CURSOR;
+ NSRectFill (NSInsetRect (r, 1, 1));
[FRAME_CURSOR_COLOR (f) set];
-
-
- if (!active_p)
- {
- /* inactive window: ignore what we just set and use a hollow box */
- cursorType = HOLLOW_BOX_CURSOR;
- }
-
-#ifdef NS_IMPL_COCOA
- NSDisableScreenUpdates ();
-#endif
-
- switch (cursorType)
- {
- case NO_CURSOR: // no_highlight:
- break;
- case FILLED_BOX_CURSOR: //filled_box:
- NSRectFill (r);
- drawGlyph = 1;
- break;
- case HOLLOW_BOX_CURSOR: //hollow_box:
- NSRectFill (r);
- [FRAME_BACKGROUND_COLOR (f) set];
- NSRectFill (NSInsetRect (r, 1, 1));
- [FRAME_CURSOR_COLOR (f) set];
- drawGlyph = 1;
- break;
- case HBAR_CURSOR: // underscore:
- s = r;
- s.origin.y += lrint (0.75 * s.size.height);
- s.size.height = cursor_width; //lrint (s.size.height * 0.25);
- NSRectFill (s);
- break;
- case BAR_CURSOR: //bar:
- s = r;
- s.size.width = cursor_width;
- NSRectFill (s);
- drawGlyph = 1;
- break;
- }
+ break;
+ case HBAR_CURSOR:
+ s = r;
+ s.origin.y += lrint (0.75 * s.size.height);
+ s.size.width = min (FRAME_COLUMN_WIDTH (f), s.size.width);
+ s.size.height = lrint (s.size.height * 0.25);
+ NSRectFill (s);
+ break;
+ case BAR_CURSOR:
+ s = r;
+ s.size.width = min (cursor_width, 2); //FIXME(see above)
+ NSRectFill (s);
+ break;
}
ns_unfocus (f);
- /* if needed, draw the character under the cursor */
- if (drawGlyph)
- draw_phys_cursor_glyph (w, glyph_row, hl);
+ /* draw the character under the cursor */
+ if (cursorToDraw != NO_CURSOR)
+ draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
#ifdef NS_IMPL_COCOA
NSEnableScreenUpdates ();
struct face *face;
NSRect r = NSMakeRect (x, y0, 2, y1-y0);
+ NSTRACE (ns_draw_vertical_window_border);
+
face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
if (face)
[ns_lookup_indexed_color(face->foreground, f) set];
NSTRACE (ns_draw_glyph_string);
- if (s->next && s->right_overhang && !s->for_overlaps/* && s->hl != DRAW_CURSOR*/)
+ if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
{
int width;
struct glyph_string *next;
- for (width = 0, next = s->next; next;
+ for (width = 0, next = s->next;
+ next && width < s->right_overhang;
width += next->width, next = next->next)
if (next->first_glyph->type != IMAGE_GLYPH)
{
struct ns_display_info *dpyinfo = terminal->display_info.ns;
int i;
- /* Protect against recursive calls. Fdelete_frame in
+ /* Protect against recursive calls. delete_frame in
delete_terminal calls us back when it deletes our last frame. */
if (!terminal->name)
return;
[NSApp setServicesProvider: NSApp];
ns_send_appdefined (-2);
}
-
+
- (void) terminate: (id)sender
{
if (newFont = [sender convertFont:
((struct nsfont_info *)face->font)->nsfont])
{
+ SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
+
emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
emacs_event->modifiers = 0;
emacs_event->code = KEY_NS_CHANGE_FONT;
}
-- (void)mouseUp: (NSEvent *)theEvent
+- (void)rightMouseDown: (NSEvent *)theEvent
{
- NSTRACE (mouseUp);
+ NSTRACE (rightMouseDown);
[self mouseDown: theEvent];
}
-- (void)rightMouseDown: (NSEvent *)theEvent
+- (void)otherMouseDown: (NSEvent *)theEvent
{
- NSTRACE (rightMouseDown);
+ NSTRACE (otherMouseDown);
+ [self mouseDown: theEvent];
+}
+
+
+- (void)mouseUp: (NSEvent *)theEvent
+{
+ NSTRACE (mouseUp);
[self mouseDown: theEvent];
}
}
+- (void)otherMouseUp: (NSEvent *)theEvent
+{
+ NSTRACE (otherMouseUp);
+ [self mouseDown: theEvent];
+}
+
+
- (void) scrollWheel: (NSEvent *)theEvent
{
NSTRACE (scrollWheel);
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
Lisp_Object frame;
- NSTRACE (mouseMoved);
+// NSTRACE (mouseMoved);
last_mouse_movement_time = EV_TIMESTAMP (e);
last_mouse_motion_position
}
+- (void)otherMouseDragged: (NSEvent *)e
+{
+ NSTRACE (otherMouseDragged);
+ [self mouseMoved: e];
+}
+
+
- (BOOL)windowShouldClose: (id)sender
{
NSEvent *e =[[self window] currentEvent];
- (void)windowDidBecomeKey: (NSNotification *)notification
+/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
{
- int val = ns_lisp_to_cursor_type (get_frame_param (emacsframe, Qcursor_type));
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
struct frame *old_focus = dpyinfo->x_focus_frame;
if (emacsframe != old_focus)
dpyinfo->x_focus_frame = emacsframe;
- /*/last_mouse_frame = emacsframe;? */
-
- if (val >= 0)
- {
- FRAME_NEW_CURSOR (emacsframe) = val;
-/* x_update_cursor (emacsframe, 1); // will happen in ns_frame_rehighlight */
- }
-
ns_frame_rehighlight (emacsframe);
if (emacs_event)
- (void)windowDidResignKey: (NSNotification *)notification
+/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
{
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
NSTRACE (windowDidResignKey);
- if (!windowClosing && [[self window] isVisible] == YES)
- {
- FRAME_NEW_CURSOR (emacsframe) = hollow_box;
- x_update_cursor (emacsframe, 1);
- FRAME_LAST_INACTIVE (emacsframe) = YES;
- }
-
- if (dpyinfo->x_highlight_frame == emacsframe)
- dpyinfo->x_highlight_frame = 0;
if (dpyinfo->x_focus_frame == emacsframe)
dpyinfo->x_focus_frame = 0;
- if (dpyinfo->mouse_face_mouse_frame == emacsframe)
+ ns_frame_rehighlight (emacsframe);
+
+ /* FIXME: for some reason needed on second and subsequent clicks away
+ from sole-frame Emacs to get hollow box to show */
+ if (!windowClosing && [[self window] isVisible] == YES)
{
- clear_mouse_face (dpyinfo);
- dpyinfo->mouse_face_mouse_frame = 0;
+ x_update_cursor (emacsframe, 1);
+ x_set_frame_alpha (emacsframe);
}
if (emacs_event)
#endif
[expandSpaceSlider setFloatValue: prevExpandSpace];
- [cursorTypeMatrix selectCellWithTag: (cursorType == filled_box ? 1 :
- (cursorType == bar ? 2 :
- (cursorType == underscore ? 3 : 4)))];
+ [cursorTypeMatrix selectCellWithTag: (cursorType == FILLED_BOX_CURSOR ? 1 :
+ (cursorType == BAR_CURSOR ? 2 :
+ (cursorType == HBAR_CURSOR ? 3 : 4)))];
selectItemWithTag (alternateModMenu,
parse_solitary_modifier (ns_alternate_modifier));
selectItemWithTag (commandModMenu,
- (void) setValuesFromPanel
{
- int cursorTag = [[cursorTypeMatrix selectedCell] tag];
int altTag = [[alternateModMenu selectedItem] tag];
int cmdTag = [[commandModMenu selectedItem] tag];
#ifdef NS_IMPL_COCOA
int fnTag = [[functionModMenu selectedItem] tag];
#endif
float expandSpace = [expandSpaceSlider floatValue];
+ int cursorTag = [[cursorTypeMatrix selectedCell] tag];
+ Lisp_Object cursor_type = ns_cursor_type_to_lisp
+ ( cursorTag == 1 ? FILLED_BOX_CURSOR
+ : cursorTag == 2 ? BAR_CURSOR
+ : cursorTag == 3 ? HBAR_CURSOR : HOLLOW_BOX_CURSOR);
if (expandSpace != prevExpandSpace)
{
x_set_window_size (frame, 0, frame->text_cols, frame->text_lines); */
prevExpandSpace = expandSpace;
}
- FRAME_NEW_CURSOR (frame)
- = (cursorTag == 1 ? filled_box
- : cursorTag == 2 ? bar
- : cursorTag == 3 ? underscore : hollow_box);
- store_frame_param (frame, Qcursor_type,
- ns_cursor_type_to_lisp (FRAME_NEW_CURSOR (frame)));
+
+ store_frame_param (frame, Qcursor_type, cursor_type);
+ ns_set_cursor_type(frame, cursor_type, Qnil); /* FIXME: do only if changed */
+
ns_alternate_modifier = ns_mod_to_lisp (altTag);
ns_command_modifier = ns_mod_to_lisp (cmdTag);
#ifdef NS_IMPL_COCOA
char *name = xmalloc (180);
int i, len;
const char *ret;
-
+
if (!strncmp (xlfd, "--", 2))
sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
else
/* Tell emacs about this window system. */
Fprovide (intern ("ns"), Qnil);
- /* TODO: try to move this back into lisp, ns-win.el loaded too late
- right now */
- {
- Lisp_Object args[3] = { intern ("ns-version-string"), build_string ("9.0"),
- build_string ("NS Window system port version number.") };
- Fdefconst (Flist (3, args));
- }
}