a28cba6ad267c2f1905f39ab2fb13e5b19216bc2
[mono.git] / bockbuild / mac-sdk / patches / gtk / 0050-nsview-clip-text-field-cursor-drawing.patch
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
5
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..
9 ---
10  gtk/gtknsview.c |  162 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
11  1 file changed, 159 insertions(+), 3 deletions(-)
12
13 diff --git a/gtk/gtknsview.c b/gtk/gtknsview.c
14 index bc3cbfb..5e3aa59 100644
15 --- a/gtk/gtknsview.c
16 +++ b/gtk/gtknsview.c
17 @@ -145,14 +145,23 @@ static void   gtk_ns_view_swizzle_draw_rect_recursive (NSView      *view,
18                                                         gpointer     associated_object);
19
20  @implementation NSView (myDidAddSubview)
21 -- (void) myDidAddSubview:(NSView *)aView
22 +- (void) myDidAddSubview: (NSView *) aView
23  {
24    void *associated_object;
25
26    associated_object = objc_getAssociatedObject (self, "gtknsview");
27
28    if (associated_object)
29 -    gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtknsview", associated_object);
30 +    {
31 +      gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtknsview", associated_object);
32 +    }
33 +  else
34 +    {
35 +      associated_object = objc_getAssociatedObject (self, "gtkwindow");
36 +
37 +      if (associated_object)
38 +        gtk_ns_view_swizzle_draw_rect_recursive (aView, "gtkwindow", associated_object);
39 +    }
40
41    [self myDidAddSubview:aView];
42  }
43 @@ -256,6 +265,110 @@ static void   gtk_ns_view_swizzle_draw_rect_recursive (NSView      *view,
44  }
45  @end
46
47 +@implementation NSTextView (myDrawInsertionPointInRect)
48 +- (void) myDrawInsertionPointInRect: (NSRect) aRect
49 +                              color: (NSColor *) aColor
50 +                           turnedOn: (BOOL) flag
51 +{
52 +  GtkNSView *ns_view;
53 +  GtkWidget *viewport;
54 +  CGContextRef cg_context;
55 +
56 +  ns_view = (GtkNSView *) objc_getAssociatedObject (self, "gtknsview");
57 +
58 +  if (! ns_view && ([self class] == [NSTextView class]))
59 +    {
60 +      /*  if it's not a GtkNSView, check if it's the NSWindow's cell
61 +       *  editor editing an NSTextField managed by a GtkNSView
62 +       */
63 +      GtkWindow *window = (GtkWindow *) objc_getAssociatedObject (self, "gtkwindow");
64 +
65 +      if (GTK_IS_WINDOW (window))
66 +        {
67 +          GtkWidget *focus = gtk_window_get_focus (window);
68 +
69 +          if (GTK_IS_NS_VIEW (focus))
70 +            ns_view = GTK_NS_VIEW (focus);
71 +        }
72 +    }
73 +
74 +  if (! ns_view ||
75 +      ns_view->priv->view != [ns_view->priv->view ancestorSharedWithView: self])
76 +    {
77 +      [self myDrawInsertionPointInRect: aRect
78 +                                 color: aColor
79 +                              turnedOn: flag];
80 +      return;
81 +    }
82 +
83 +  cg_context = [[NSGraphicsContext currentContext] graphicsPort];
84 +  CGContextSaveGState (cg_context);
85 +
86 +  for (viewport = gtk_widget_get_ancestor (GTK_WIDGET (ns_view), GTK_TYPE_VIEWPORT);
87 +       viewport;
88 +       viewport = gtk_widget_get_ancestor (gtk_widget_get_parent (viewport),
89 +                                           GTK_TYPE_VIEWPORT))
90 +    {
91 +      GdkWindow *window;
92 +      GtkAllocation viewport_allocation;
93 +      CGRect rect;
94 +
95 +      gtk_widget_get_allocation (viewport, &viewport_allocation);
96 +
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
101 +       */
102 +      window = gtk_widget_get_parent_window (viewport);
103 +
104 +      viewport_allocation.width = gdk_window_get_width (window);
105 +      viewport_allocation.height = gdk_window_get_height (window);
106 +
107 +      if (gtk_viewport_get_shadow_type (GTK_VIEWPORT (viewport)) != GTK_SHADOW_NONE)
108 +        {
109 +          GtkStyle *style = gtk_widget_get_style (viewport);
110 +
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;
115 +        }
116 +
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);
122 +
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;
127 +
128 +      /*  need to translate rect if this is not the view itself but a subview  */
129 +      if (ns_view->priv->view != self)
130 +        {
131 +          NSRect offset = NSMakeRect (0, 0, 0, 0);
132 +
133 +          offset = [ns_view->priv->view convertRect: offset
134 +                                           fromView: self];
135 +
136 +          rect.origin.x -= offset.origin.x;
137 +          rect.origin.y -= offset.origin.y;
138 +        }
139 +
140 +      CGContextClipToRect (cg_context, rect);
141 +    }
142 +
143 +  [self myDrawInsertionPointInRect: aRect
144 +                             color: aColor
145 +                          turnedOn: flag];
146 +
147 +  CGContextRestoreGState (cg_context);
148 +}
149 +@end
150 +
151  static void
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));
156      }
157
158 -
159    objc_setAssociatedObject (view, associated_key, (id) associated_object,
160                              OBJC_ASSOCIATION_ASSIGN);
161
162 @@ -325,6 +437,49 @@ gtk_ns_view_swizzle_draw_rect_recursive (NSView      *view,
163  }
164
165  static void
166 +gtk_ns_view_replace_draw_insertion_point (void)
167 +{
168 +  static volatile gsize draw_insertion_point_replaced = 0;
169 +
170 +  /* We replace the drawInsertPointInRect:color:turnedOn: method of the
171 +   * NSTextView class. This should only be done once per application
172 +   * instance.
173 +   */
174 +
175 +  if (g_once_init_enter (&draw_insertion_point_replaced))
176 +    {
177 +      Method original_drawInsertionPointInRect;
178 +      Method my_drawInsertionPointInRect;
179 +      IMP original_implementation;
180 +      Class text_view_class = [NSTextView class];
181 +
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
185 +       * implementation.
186 +       */
187 +      original_drawInsertionPointInRect = class_getInstanceMethod (text_view_class,
188 +                                                                   @selector (drawInsertionPointInRect:color:turnedOn:));
189 +      original_implementation = method_getImplementation (original_drawInsertionPointInRect);
190 +
191 +      my_drawInsertionPointInRect = class_getInstanceMethod (text_view_class,
192 +                                                             @selector (myDrawInsertionPointInRect:color:turnedOn:));
193 +
194 +      class_replaceMethod (text_view_class,
195 +                           @selector (drawInsertionPointInRect:color:turnedOn:),
196 +                           method_getImplementation (my_drawInsertionPointInRect),
197 +                           method_getTypeEncoding (my_drawInsertionPointInRect));
198 +
199 +      class_replaceMethod (text_view_class,
200 +                           @selector (myDrawInsertionPointInRect:color:turnedOn:),
201 +                           original_implementation,
202 +                           method_getTypeEncoding (original_drawInsertionPointInRect));
203 +
204 +      g_once_init_leave (&draw_insertion_point_replaced, TRUE);
205 +    }
206 +}
207 +
208 +static void
209  gtk_ns_view_constructed (GObject *object)
210  {
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)));
214  #endif
215
216 +  gtk_ns_view_replace_draw_insertion_point ();
217    gtk_ns_view_swizzle_draw_rect_recursive (ns_view->priv->view,
218                                             "gtknsview", ns_view);
219  }
220 --
221 1.7.10.2 (Apple Git-33)