1 From daf0f5ecb7b9a71d93d7e41b000369d977ea4816 Mon Sep 17 00:00:00 2001
2 From: Michael Natterer <mitch@gimp.org>
3 Date: Thu, 25 Apr 2013 14:52:18 +0200
4 Subject: [PATCH 50/68] nsview: clip text field cursor drawing
6 by replacing (not "normal" swizzling) drawInsertionPointInRect. This
7 fixes cursor clipping for the *blinking* cursor, but not if the
8 cusor moves. Patch patially from Kris..
10 gtk/gtknsview.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
11 1 file changed, 159 insertions(+), 3 deletions(-)
13 diff --git a/gtk/gtknsview.c b/gtk/gtknsview.c
14 index bc3cbfb..5e3aa59 100644
17 @@ -145,14 +145,23 @@ static void gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
18 gpointer associated_object);
20 @implementation NSView (myDidAddSubview)
21 -- (void) myDidAddSubview:(NSView *)aView
22 +- (void) myDidAddSubview: (NSView *) aView
24 void *associated_object;
26 associated_object = objc_getAssociatedObject (self, "gtknsview");
28 if (associated_object)
29 - gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtknsview", associated_object);
31 + gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtknsview", associated_object);
35 + associated_object = objc_getAssociatedObject (self, "gtkwindow");
37 + if (associated_object)
38 + gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtkwindow", associated_object);
41 [self myDidAddSubview:aView];
43 @@ -256,6 +265,110 @@ static void gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
47 +@implementation NSTextView (myDrawInsertionPointInRect)
48 +- (void) myDrawInsertionPointInRect: (NSRect) aRect
49 + color: (NSColor *) aColor
50 + turnedOn: (BOOL) flag
53 + GtkWidget *viewport;
54 + CGContextRef cg_context;
56 + ns_view = (GtkNSView *) objc_getAssociatedObject (self, "gtknsview");
58 + if (! ns_view && ([self class] == [NSTextView class]))
60 + /* if it's not a GtkNSView, check if it's the NSWindow's cell
61 + * editor editing an NSTextField managed by a GtkNSView
63 + GtkWindow *window = (GtkWindow *) objc_getAssociatedObject (self, "gtkwindow");
65 + if (GTK_IS_WINDOW (window))
67 + GtkWidget *focus = gtk_window_get_focus (window);
69 + if (GTK_IS_NS_VIEW (focus))
70 + ns_view = GTK_NS_VIEW (focus);
75 + ns_view->priv->view != [ns_view->priv->view ancestorSharedWithView: self])
77 + [self myDrawInsertionPointInRect: aRect
83 + cg_context = [[NSGraphicsContext currentContext] graphicsPort];
84 + CGContextSaveGState (cg_context);
86 + for (viewport = gtk_widget_get_ancestor (GTK_WIDGET (ns_view), GTK_TYPE_VIEWPORT);
88 + viewport = gtk_widget_get_ancestor (gtk_widget_get_parent (viewport),
92 + GtkAllocation viewport_allocation;
95 + gtk_widget_get_allocation (viewport, &viewport_allocation);
97 + /* evil: don't clip to the viewport's width/height but to that
98 + * of its parent window, because we know we hacked an
99 + * overshoot_window into GtkScrolledWindow and need to restrict
100 + * rendering to its area
102 + window = gtk_widget_get_parent_window (viewport);
104 + viewport_allocation.width = gdk_window_get_width (window);
105 + viewport_allocation.height = gdk_window_get_height (window);
107 + if (gtk_viewport_get_shadow_type (GTK_VIEWPORT (viewport)) != GTK_SHADOW_NONE)
109 + GtkStyle *style = gtk_widget_get_style (viewport);
111 + viewport_allocation.x += style->xthickness;
112 + viewport_allocation.y += style->ythickness;
113 + viewport_allocation.width -= 2 * style->xthickness;
114 + viewport_allocation.height -= 2 * style->ythickness;
117 + gtk_widget_translate_coordinates (viewport, GTK_WIDGET (ns_view),
118 + viewport_allocation.x,
119 + viewport_allocation.y,
120 + &viewport_allocation.x,
121 + &viewport_allocation.y);
123 + rect.origin.x = viewport_allocation.x;
124 + rect.origin.y = viewport_allocation.y;
125 + rect.size.width = viewport_allocation.width;
126 + rect.size.height = viewport_allocation.height;
128 + /* need to translate rect if this is not the view itself but a subview */
129 + if (ns_view->priv->view != self)
131 + NSRect offset = NSMakeRect (0, 0, 0, 0);
133 + offset = [ns_view->priv->view convertRect: offset
136 + rect.origin.x -= offset.origin.x;
137 + rect.origin.y -= offset.origin.y;
140 + CGContextClipToRect (cg_context, rect);
143 + [self myDrawInsertionPointInRect: aRect
147 + CGContextRestoreGState (cg_context);
152 gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
153 const gchar *associated_key,
154 @@ -310,7 +423,6 @@ gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
155 method_getTypeEncoding (my_didAddSubview));
159 objc_setAssociatedObject (view, associated_key, (id) associated_object,
160 OBJC_ASSOCIATION_ASSIGN);
162 @@ -325,6 +437,49 @@ gtk_ns_view_swizzle_draw_rect_recursive (NSView *view,
166 +gtk_ns_view_replace_draw_insertion_point (void)
168 + static volatile gsize draw_insertion_point_replaced = 0;
170 + /* We replace the drawInsertPointInRect:color:turnedOn: method of the
171 + * NSTextView class. This should only be done once per application
175 + if (g_once_init_enter (&draw_insertion_point_replaced))
177 + Method original_drawInsertionPointInRect;
178 + Method my_drawInsertionPointInRect;
179 + IMP original_implementation;
180 + Class text_view_class = [NSTextView class];
182 + /* Get the original method and an explicit reference to the
183 + * implementation behind this method. This because after the
184 + * first replace method call, the method will point at a different
187 + original_drawInsertionPointInRect = class_getInstanceMethod (text_view_class,
188 + @selector (drawInsertionPointInRect:color:turnedOn:));
189 + original_implementation = method_getImplementation (original_drawInsertionPointInRect);
191 + my_drawInsertionPointInRect = class_getInstanceMethod (text_view_class,
192 + @selector (myDrawInsertionPointInRect:color:turnedOn:));
194 + class_replaceMethod (text_view_class,
195 + @selector (drawInsertionPointInRect:color:turnedOn:),
196 + method_getImplementation (my_drawInsertionPointInRect),
197 + method_getTypeEncoding (my_drawInsertionPointInRect));
199 + class_replaceMethod (text_view_class,
200 + @selector (myDrawInsertionPointInRect:color:turnedOn:),
201 + original_implementation,
202 + method_getTypeEncoding (original_drawInsertionPointInRect));
204 + g_once_init_leave (&draw_insertion_point_replaced, TRUE);
209 gtk_ns_view_constructed (GObject *object)
211 GtkNSView *ns_view = GTK_NS_VIEW (object);
212 @@ -340,6 +495,7 @@ gtk_ns_view_constructed (GObject *object)
213 gtk_widget_get_can_focus (GTK_WIDGET (ns_view)));
216 + gtk_ns_view_replace_draw_insertion_point ();
217 gtk_ns_view_swizzle_draw_rect_recursive (ns_view->priv->view,
218 "gtknsview", ns_view);
221 1.7.10.2 (Apple Git-33)