From 8daff6e1c77f0aec9e1e7fd57c5f228a4677e5a0 Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Mon, 14 May 2012 14:27:58 +0200 Subject: osxvideosink: implement the navigation interface --- sys/osxvideo/cocoawindow.h | 4 ++ sys/osxvideo/cocoawindow.m | 137 +++++++++++++++++++++++++++++++++++++++----- sys/osxvideo/osxvideosink.m | 74 +++++++++++++++++++++++- 3 files changed, 199 insertions(+), 16 deletions(-) (limited to 'sys') diff --git a/sys/osxvideo/cocoawindow.h b/sys/osxvideo/cocoawindow.h index 7324cc70a..7eec95333 100644 --- a/sys/osxvideo/cocoawindow.h +++ b/sys/osxvideo/cocoawindow.h @@ -29,6 +29,7 @@ #import #import #import +#import struct _GstOSXImage; @@ -44,6 +45,8 @@ struct _GstOSXImage; BOOL fullscreen; NSOpenGLContext* fullScreenContext; NSOpenGLContext* actualContext; + NSTrackingArea *trackingArea; + GstNavigation *navigation; } - (void) drawQuad; - (void) drawRect: (NSRect) rect; @@ -60,6 +63,7 @@ struct _GstOSXImage; - (void) haveSuperviewReal: (NSMutableArray *)closure; - (void) addToSuperview: (NSView *)superview; - (void) removeFromSuperview: (id)unused; +- (void) setNavigation: (GstNavigation *) nav; @end diff --git a/sys/osxvideo/cocoawindow.m b/sys/osxvideo/cocoawindow.m index ed24fadc2..b4f986add 100644 --- a/sys/osxvideo/cocoawindow.m +++ b/sys/osxvideo/cocoawindow.m @@ -82,21 +82,6 @@ [self setAcceptsMouseMovedEvents:YES]; } -- (void) sendEvent:(NSEvent *) event { - BOOL taken = NO; - - GST_DEBUG ("event %p type:%d", event,(gint)[event type]); - - if ([event type] == NSKeyDown) { - } - /*taken = [gstview keyDown:event]; */ - - if (!taken) { - [super sendEvent:event]; - } -} - - @end @@ -144,6 +129,13 @@ GST_LOG ("Width: %d Height: %d", width, height); + trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] + options: (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow) + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; + [self initTextures]; return self; } @@ -429,4 +421,119 @@ [super dealloc]; } + +- (void)updateTrackingAreas { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + trackingArea = [[NSTrackingArea alloc] initWithRect: [self bounds] + options: (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow) + owner:self userInfo:nil]; + [self addTrackingArea:trackingArea]; +} + +- (BOOL)acceptsFirstResponder { + return YES; +} + +- (void) setNavigation:(GstNavigation *)nav +{ + navigation = nav; +} + +- (void)sendMouseEvent:(NSEvent *)event: (const char *)event_name +{ + NSPoint location; + NSRect bounds; + gint button; + gint view_width, view_height; + gdouble x, y; + + if (!navigation) + return; + + switch ([event type]) { + case NSMouseMoved: + button = 0; + break; + case NSLeftMouseDown: + case NSLeftMouseUp: + button = 1; + break; + case NSRightMouseDown: + case NSRightMouseUp: + button = 2; + break; + default: + button = 3; + break; + } + + location = [self convertPoint:[event locationInWindow] fromView:nil]; + + /* scale X and Y locations to the frame size */ + bounds = [self bounds]; + view_width = bounds.size.width; + view_height = bounds.size.height; + + x = ((gdouble) location.x / view_width) * width; + y = ((gdouble) location.y / view_height) * height; + + /* invert Y */ + y = (1 - y / height) * height; + + gst_navigation_send_mouse_event (navigation, event_name, button, + x, y); +} + +- (void)sendKeyEvent:(NSEvent *)event: (const char *)event_name +{ + NSString *keyCharStr = [event charactersIgnoringModifiers]; + gchar * key_str; + + if (!navigation) + return; + + if ( [keyCharStr length] == 0 ) + return; + + if ( [keyCharStr length] == 1 ) { + key_str = g_strdup_printf("%c", [keyCharStr characterAtIndex:0]); + gst_navigation_send_key_event(navigation, event_name, (const gchar *) key_str); + g_free(key_str); + } +} + +- (void)keyDown:(NSEvent *) event; +{ + [self sendKeyEvent: event: "key-press"]; +} + +- (void)keyUp:(NSEvent *) event; +{ + [self sendKeyEvent: event: "key-release"]; +} + +- (void)mouseDown:(NSEvent *) event; +{ + [self sendMouseEvent:event: "mouse-button-press"]; +} + +- (void)mouseUp:(NSEvent *) event; +{ + [self sendMouseEvent:event: "mouse-button-release"]; +} + +- (void)mouseMoved:(NSEvent *)event; +{ + [self sendMouseEvent:event: "mouse-move"]; +} + +- (void)mouseEntered:(NSEvent *)event; +{ +} + +- (void)mouseExited:(NSEvent *)event; +{ +} + @end diff --git a/sys/osxvideo/osxvideosink.m b/sys/osxvideo/osxvideosink.m index 16bbaed87..d836a8fe3 100644 --- a/sys/osxvideo/osxvideosink.m +++ b/sys/osxvideo/osxvideosink.m @@ -148,6 +148,7 @@ gst_osx_video_sink_osxwindow_create (GstOSXVideoSink * osxvideosink, gint width, GST_INFO_OBJECT (osxvideosink, "no superview"); } } + [osxwindow->gstview setNavigation: GST_NAVIGATION(osxvideosink)]; [pool release]; @@ -416,7 +417,7 @@ gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass) static gboolean gst_osx_video_sink_interface_supported (GstImplementsInterface * iface, GType type) { - g_assert (type == GST_TYPE_X_OVERLAY); + g_assert (type == GST_TYPE_X_OVERLAY || type == GST_TYPE_NAVIGATION); return TRUE; } @@ -426,6 +427,72 @@ gst_osx_video_sink_interface_init (GstImplementsInterfaceClass * klass) klass->supported = gst_osx_video_sink_interface_supported; } +static void +gst_osx_video_sink_navigation_send_event (GstNavigation * navigation, + GstStructure * structure) +{ + GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (navigation); + GstPad *peer; + GstEvent *event; + GstVideoRectangle src, dst, result; + gdouble x, y, xscale = 1.0, yscale = 1.0; + + peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (osxvideosink)); + + if (!peer || !osxvideosink->osxwindow) + return; + + event = gst_event_new_navigation (structure); + + /* FIXME: Use this when this sink is capable of keeping the display + * aspect ratio */ + if (0) { //(osxvideosink->keep_aspect) { + /* We get the frame position using the calculated geometry from _setcaps + that respect pixel aspect ratios */ + src.w = GST_VIDEO_SINK_WIDTH (osxvideosink); + src.h = GST_VIDEO_SINK_HEIGHT (osxvideosink); + //dst.w = osxvideosink->osxwindow->gstview->width; + //dst.w = osxvideosink->osxwindow->gstview->height; + + gst_video_sink_center_rect (src, dst, &result, TRUE); + //result.x += osxvideosink->gstview->x; + //result.y += osxvideosink->gstview->y; + } else { + result.x = 0; + result.y = 0; + result.w = osxvideosink->osxwindow->width; + result.h = osxvideosink->osxwindow->height; + } + + /* We calculate scaling using the original video frames geometry to include + pixel aspect ratio scaling. */ + xscale = (gdouble) osxvideosink->osxwindow->width / result.w; + yscale = (gdouble) osxvideosink->osxwindow->height / result.h; + + /* Converting pointer coordinates to the non scaled geometry */ + if (gst_structure_get_double (structure, "pointer_x", &x)) { + x = MIN (x, result.x + result.w); + x = MAX (x - result.x, 0); + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, + (gdouble) x * xscale, NULL); + } + if (gst_structure_get_double (structure, "pointer_y", &y)) { + y = MIN (y, result.y + result.h); + y = MAX (y - result.y, 0); + gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, + (gdouble) y * yscale, NULL); + } + + gst_pad_send_event (peer, event); + gst_object_unref (peer); +} + +static void +gst_osx_video_sink_navigation_init (GstNavigationInterface * iface) +{ + iface->send_event = gst_osx_video_sink_navigation_send_event; +} + static void gst_osx_video_sink_set_window_handle (GstXOverlay * overlay, guintptr handle_id) { @@ -500,6 +567,11 @@ gst_osx_video_sink_get_type (void) NULL, }; + static const GInterfaceInfo navigation_info = { + (GInterfaceInitFunc) gst_osx_video_sink_navigation_init, + NULL, + NULL, + }; osxvideosink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstOSXVideoSink", &osxvideosink_info, 0); -- cgit v1.2.3