222 lines
8.1 KiB
Diff
222 lines
8.1 KiB
Diff
|
From daf0f5ecb7b9a71d93d7e41b000369d977ea4816 Mon Sep 17 00:00:00 2001
|
||
|
From: Michael Natterer <mitch@gimp.org>
|
||
|
Date: Thu, 25 Apr 2013 14:52:18 +0200
|
||
|
Subject: [PATCH 50/68] nsview: clip text field cursor drawing
|
||
|
|
||
|
by replacing (not "normal" swizzling) drawInsertionPointInRect. This
|
||
|
fixes cursor clipping for the *blinking* cursor, but not if the
|
||
|
cusor moves. Patch patially from Kris..
|
||
|
---
|
||
|
gtk/gtknsview.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||
|
1 file changed, 159 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/gtk/gtknsview.c b/gtk/gtknsview.c
|
||
|
index bc3cbfb..5e3aa59 100644
|
||
|
--- a/gtk/gtknsview.c
|
||
|
+++ b/gtk/gtknsview.c
|
||
|
@@ -145,14 +145,23 @@ static void gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
|
||
|
gpointer associated_object);
|
||
|
|
||
|
@implementation NSView (myDidAddSubview)
|
||
|
-- (void) myDidAddSubview:(NSView *)aView
|
||
|
+- (void) myDidAddSubview: (NSView *) aView
|
||
|
{
|
||
|
void *associated_object;
|
||
|
|
||
|
associated_object = objc_getAssociatedObject (self, "gtknsview");
|
||
|
|
||
|
if (associated_object)
|
||
|
- gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtknsview", associated_object);
|
||
|
+ {
|
||
|
+ gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtknsview", associated_object);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ associated_object = objc_getAssociatedObject (self, "gtkwindow");
|
||
|
+
|
||
|
+ if (associated_object)
|
||
|
+ gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtkwindow", associated_object);
|
||
|
+ }
|
||
|
|
||
|
[self myDidAddSubview:aView];
|
||
|
}
|
||
|
@@ -256,6 +265,110 @@ static void gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
|
||
|
}
|
||
|
@end
|
||
|
|
||
|
+@implementation NSTextView (myDrawInsertionPointInRect)
|
||
|
+- (void) myDrawInsertionPointInRect: (NSRect) aRect
|
||
|
+ color: (NSColor *) aColor
|
||
|
+ turnedOn: (BOOL) flag
|
||
|
+{
|
||
|
+ GtkNSView *ns_view;
|
||
|
+ GtkWidget *viewport;
|
||
|
+ CGContextRef cg_context;
|
||
|
+
|
||
|
+ ns_view = (GtkNSView *) objc_getAssociatedObject (self, "gtknsview");
|
||
|
+
|
||
|
+ if (! ns_view && ([self class] == [NSTextView class]))
|
||
|
+ {
|
||
|
+ /* if it's not a GtkNSView, check if it's the NSWindow's cell
|
||
|
+ * editor editing an NSTextField managed by a GtkNSView
|
||
|
+ */
|
||
|
+ GtkWindow *window = (GtkWindow *) objc_getAssociatedObject (self, "gtkwindow");
|
||
|
+
|
||
|
+ if (GTK_IS_WINDOW (window))
|
||
|
+ {
|
||
|
+ GtkWidget *focus = gtk_window_get_focus (window);
|
||
|
+
|
||
|
+ if (GTK_IS_NS_VIEW (focus))
|
||
|
+ ns_view = GTK_NS_VIEW (focus);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (! ns_view ||
|
||
|
+ ns_view->priv->view != [ns_view->priv->view ancestorSharedWithView: self])
|
||
|
+ {
|
||
|
+ [self myDrawInsertionPointInRect: aRect
|
||
|
+ color: aColor
|
||
|
+ turnedOn: flag];
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ cg_context = [[NSGraphicsContext currentContext] graphicsPort];
|
||
|
+ CGContextSaveGState (cg_context);
|
||
|
+
|
||
|
+ for (viewport = gtk_widget_get_ancestor (GTK_WIDGET (ns_view), GTK_TYPE_VIEWPORT);
|
||
|
+ viewport;
|
||
|
+ viewport = gtk_widget_get_ancestor (gtk_widget_get_parent (viewport),
|
||
|
+ GTK_TYPE_VIEWPORT))
|
||
|
+ {
|
||
|
+ GdkWindow *window;
|
||
|
+ GtkAllocation viewport_allocation;
|
||
|
+ CGRect rect;
|
||
|
+
|
||
|
+ gtk_widget_get_allocation (viewport, &viewport_allocation);
|
||
|
+
|
||
|
+ /* evil: don't clip to the viewport's width/height but to that
|
||
|
+ * of its parent window, because we know we hacked an
|
||
|
+ * overshoot_window into GtkScrolledWindow and need to restrict
|
||
|
+ * rendering to its area
|
||
|
+ */
|
||
|
+ window = gtk_widget_get_parent_window (viewport);
|
||
|
+
|
||
|
+ viewport_allocation.width = gdk_window_get_width (window);
|
||
|
+ viewport_allocation.height = gdk_window_get_height (window);
|
||
|
+
|
||
|
+ if (gtk_viewport_get_shadow_type (GTK_VIEWPORT (viewport)) != GTK_SHADOW_NONE)
|
||
|
+ {
|
||
|
+ GtkStyle *style = gtk_widget_get_style (viewport);
|
||
|
+
|
||
|
+ viewport_allocation.x += style->xthickness;
|
||
|
+ viewport_allocation.y += style->ythickness;
|
||
|
+ viewport_allocation.width -= 2 * style->xthickness;
|
||
|
+ viewport_allocation.height -= 2 * style->ythickness;
|
||
|
+ }
|
||
|
+
|
||
|
+ gtk_widget_translate_coordinates (viewport, GTK_WIDGET (ns_view),
|
||
|
+ viewport_allocation.x,
|
||
|
+ viewport_allocation.y,
|
||
|
+ &viewport_allocation.x,
|
||
|
+ &viewport_allocation.y);
|
||
|
+
|
||
|
+ rect.origin.x = viewport_allocation.x;
|
||
|
+ rect.origin.y = viewport_allocation.y;
|
||
|
+ rect.size.width = viewport_allocation.width;
|
||
|
+ rect.size.height = viewport_allocation.height;
|
||
|
+
|
||
|
+ /* need to translate rect if this is not the view itself but a subview */
|
||
|
+ if (ns_view->priv->view != self)
|
||
|
+ {
|
||
|
+ NSRect offset = NSMakeRect (0, 0, 0, 0);
|
||
|
+
|
||
|
+ offset = [ns_view->priv->view convertRect: offset
|
||
|
+ fromView: self];
|
||
|
+
|
||
|
+ rect.origin.x -= offset.origin.x;
|
||
|
+ rect.origin.y -= offset.origin.y;
|
||
|
+ }
|
||
|
+
|
||
|
+ CGContextClipToRect (cg_context, rect);
|
||
|
+ }
|
||
|
+
|
||
|
+ [self myDrawInsertionPointInRect: aRect
|
||
|
+ color: aColor
|
||
|
+ turnedOn: flag];
|
||
|
+
|
||
|
+ CGContextRestoreGState (cg_context);
|
||
|
+}
|
||
|
+@end
|
||
|
+
|
||
|
static void
|
||
|
gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
|
||
|
const gchar *associated_key,
|
||
|
@@ -310,7 +423,6 @@ gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
|
||
|
method_getTypeEncoding (my_didAddSubview));
|
||
|
}
|
||
|
|
||
|
-
|
||
|
objc_setAssociatedObject (view, associated_key, (id) associated_object,
|
||
|
OBJC_ASSOCIATION_ASSIGN);
|
||
|
|
||
|
@@ -325,6 +437,49 @@ gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
+gtk_ns_view_replace_draw_insertion_point (void)
|
||
|
+{
|
||
|
+ static volatile gsize draw_insertion_point_replaced = 0;
|
||
|
+
|
||
|
+ /* We replace the drawInsertPointInRect:color:turnedOn: method of the
|
||
|
+ * NSTextView class. This should only be done once per application
|
||
|
+ * instance.
|
||
|
+ */
|
||
|
+
|
||
|
+ if (g_once_init_enter (&draw_insertion_point_replaced))
|
||
|
+ {
|
||
|
+ Method original_drawInsertionPointInRect;
|
||
|
+ Method my_drawInsertionPointInRect;
|
||
|
+ IMP original_implementation;
|
||
|
+ Class text_view_class = [NSTextView class];
|
||
|
+
|
||
|
+ /* Get the original method and an explicit reference to the
|
||
|
+ * implementation behind this method. This because after the
|
||
|
+ * first replace method call, the method will point at a different
|
||
|
+ * implementation.
|
||
|
+ */
|
||
|
+ original_drawInsertionPointInRect = class_getInstanceMethod (text_view_class,
|
||
|
+ @selector (drawInsertionPointInRect:color:turnedOn:));
|
||
|
+ original_implementation = method_getImplementation (original_drawInsertionPointInRect);
|
||
|
+
|
||
|
+ my_drawInsertionPointInRect = class_getInstanceMethod (text_view_class,
|
||
|
+ @selector (myDrawInsertionPointInRect:color:turnedOn:));
|
||
|
+
|
||
|
+ class_replaceMethod (text_view_class,
|
||
|
+ @selector (drawInsertionPointInRect:color:turnedOn:),
|
||
|
+ method_getImplementation (my_drawInsertionPointInRect),
|
||
|
+ method_getTypeEncoding (my_drawInsertionPointInRect));
|
||
|
+
|
||
|
+ class_replaceMethod (text_view_class,
|
||
|
+ @selector (myDrawInsertionPointInRect:color:turnedOn:),
|
||
|
+ original_implementation,
|
||
|
+ method_getTypeEncoding (original_drawInsertionPointInRect));
|
||
|
+
|
||
|
+ g_once_init_leave (&draw_insertion_point_replaced, TRUE);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
gtk_ns_view_constructed (GObject *object)
|
||
|
{
|
||
|
GtkNSView *ns_view = GTK_NS_VIEW (object);
|
||
|
@@ -340,6 +495,7 @@ gtk_ns_view_constructed (GObject *object)
|
||
|
gtk_widget_get_can_focus (GTK_WIDGET (ns_view)));
|
||
|
#endif
|
||
|
|
||
|
+ gtk_ns_view_replace_draw_insertion_point ();
|
||
|
gtk_ns_view_swizzle_draw_rect_recursive (ns_view->priv->view,
|
||
|
"gtknsview", ns_view);
|
||
|
}
|
||
|
--
|
||
|
1.7.10.2 (Apple Git-33)
|