| | 572 | if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) |
|---|
| | 573 | { |
|---|
| | 574 | aglSetDrawable(p_vout->p_sys->agl_ctx, NULL); |
|---|
| | 575 | aglLock( p_vout ); |
|---|
| | 576 | if( p_vout->b_fullscreen ) |
|---|
| | 577 | { |
|---|
| | 578 | /* Close the fullscreen window and resume normal drawing */ |
|---|
| | 579 | vlc_value_t val; |
|---|
| | 580 | Rect viewBounds; |
|---|
| | 581 | Rect clipBounds; |
|---|
| | 582 | |
|---|
| | 583 | var_Get( p_vout->p_libvlc, "drawable", &val ); |
|---|
| | 584 | p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int; |
|---|
| | 585 | aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); |
|---|
| | 586 | |
|---|
| | 587 | var_Get( p_vout->p_libvlc, "drawable-view-top", &val ); |
|---|
| | 588 | viewBounds.top = val.i_int; |
|---|
| | 589 | var_Get( p_vout->p_libvlc, "drawable-view-left", &val ); |
|---|
| | 590 | viewBounds.left = val.i_int; |
|---|
| | 591 | var_Get( p_vout->p_libvlc, "drawable-view-bottom", &val ); |
|---|
| | 592 | viewBounds.bottom = val.i_int; |
|---|
| | 593 | var_Get( p_vout->p_libvlc, "drawable-view-right", &val ); |
|---|
| | 594 | viewBounds.right = val.i_int; |
|---|
| | 595 | var_Get( p_vout->p_libvlc, "drawable-clip-top", &val ); |
|---|
| | 596 | clipBounds.top = val.i_int; |
|---|
| | 597 | var_Get( p_vout->p_libvlc, "drawable-clip-left", &val ); |
|---|
| | 598 | clipBounds.left = val.i_int; |
|---|
| | 599 | var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val ); |
|---|
| | 600 | clipBounds.bottom = val.i_int; |
|---|
| | 601 | var_Get( p_vout->p_libvlc, "drawable-clip-right", &val ); |
|---|
| | 602 | clipBounds.right = val.i_int; |
|---|
| | 603 | |
|---|
| | 604 | aglSetCurrentContext(p_vout->p_sys->agl_ctx); |
|---|
| | 605 | aglSetViewport(p_vout, viewBounds, clipBounds); |
|---|
| | 606 | |
|---|
| | 607 | /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */ |
|---|
| | 608 | sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginHideFullscreen); |
|---|
| | 609 | } |
|---|
| | 610 | else |
|---|
| | 611 | { |
|---|
| | 612 | Rect deviceRect; |
|---|
| | 613 | |
|---|
| | 614 | GDHandle deviceHdl = GetMainDevice(); |
|---|
| | 615 | deviceRect = (*deviceHdl)->gdRect; |
|---|
| | 616 | |
|---|
| | 617 | if( !p_vout->p_sys->theWindow ) |
|---|
| | 618 | { |
|---|
| | 619 | /* Create a window */ |
|---|
| | 620 | WindowAttributes windowAttrs; |
|---|
| | 621 | |
|---|
| | 622 | windowAttrs = kWindowStandardDocumentAttributes |
|---|
| | 623 | | kWindowStandardHandlerAttribute |
|---|
| | 624 | | kWindowLiveResizeAttribute |
|---|
| | 625 | | kWindowNoShadowAttribute; |
|---|
| | 626 | |
|---|
| | 627 | windowAttrs &= (~kWindowResizableAttribute); |
|---|
| | 628 | |
|---|
| | 629 | CreateNewWindow(kDocumentWindowClass, windowAttrs, &deviceRect, &p_vout->p_sys->theWindow); |
|---|
| | 630 | if( !p_vout->p_sys->winGroup ) |
|---|
| | 631 | { |
|---|
| | 632 | CreateWindowGroup(0, &p_vout->p_sys->winGroup); |
|---|
| | 633 | SetWindowGroup(p_vout->p_sys->theWindow, p_vout->p_sys->winGroup); |
|---|
| | 634 | SetWindowGroupParent( p_vout->p_sys->winGroup, GetWindowGroupOfClass(kDocumentWindowClass) ) ; |
|---|
| | 635 | } |
|---|
| | 636 | |
|---|
| | 637 | // Window title |
|---|
| | 638 | CFStringRef titleKey = CFSTR("Fullscreen VLC media plugin"); |
|---|
| | 639 | CFStringRef windowTitle = CFCopyLocalizedString(titleKey, NULL); |
|---|
| | 640 | SetWindowTitleWithCFString(p_vout->p_sys->theWindow, windowTitle); |
|---|
| | 641 | CFRelease(titleKey); |
|---|
| | 642 | CFRelease(windowTitle); |
|---|
| | 643 | |
|---|
| | 644 | //Install event handler |
|---|
| | 645 | static const EventTypeSpec win_events[] = { |
|---|
| | 646 | { kEventClassMouse, kEventMouseDown }, |
|---|
| | 647 | { kEventClassMouse, kEventMouseMoved }, |
|---|
| | 648 | { kEventClassMouse, kEventMouseUp }, |
|---|
| | 649 | { kEventClassWindow, kEventWindowClosed }, |
|---|
| | 650 | { kEventClassWindow, kEventWindowBoundsChanged }, |
|---|
| | 651 | { kEventClassCommand, kEventCommandProcess }, |
|---|
| | 652 | { kEventClassVLCPlugin, kEventVLCPluginShowFullscreen }, |
|---|
| | 653 | { kEventClassVLCPlugin, kEventVLCPluginHideFullscreen }, |
|---|
| | 654 | }; |
|---|
| | 655 | InstallWindowEventHandler (p_vout->p_sys->theWindow, NewEventHandlerUPP (WindowEventHandler), GetEventTypeCount(win_events), win_events, p_vout, NULL); |
|---|
| | 656 | } |
|---|
| | 657 | else |
|---|
| | 658 | { |
|---|
| | 659 | /* just in case device resolution changed */ |
|---|
| | 660 | SetWindowBounds(p_vout->p_sys->theWindow, kWindowContentRgn, &deviceRect); |
|---|
| | 661 | } |
|---|
| | 662 | glClear( GL_COLOR_BUFFER_BIT ); |
|---|
| | 663 | p_vout->p_sys->agl_drawable = (AGLDrawable)GetWindowPort(p_vout->p_sys->theWindow); |
|---|
| | 664 | aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); |
|---|
| | 665 | aglSetCurrentContext(p_vout->p_sys->agl_ctx); |
|---|
| | 666 | aglSetViewport(p_vout, deviceRect, deviceRect); |
|---|
| | 667 | //aglSetFullScreen(p_vout->p_sys->agl_ctx, device_width, device_height, 0, 0); |
|---|
| | 668 | |
|---|
| | 669 | /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */ |
|---|
| | 670 | sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginShowFullscreen); |
|---|
| | 671 | } |
|---|
| | 672 | aglReshape(p_vout); |
|---|
| | 673 | aglUnlock( p_vout ); |
|---|
| | 674 | p_vout->b_fullscreen = !p_vout->b_fullscreen; |
|---|
| | 675 | p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; |
|---|
| | 676 | } |
|---|
| 625 | | aglReshape( p_vout ); |
|---|
| 626 | | } |
|---|
| 627 | | |
|---|
| | 762 | } |
|---|
| | 763 | |
|---|
| | 764 | //default window event handler |
|---|
| | 765 | static pascal OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) |
|---|
| | 766 | { |
|---|
| | 767 | OSStatus result = noErr; |
|---|
| | 768 | UInt32 class = GetEventClass (event); |
|---|
| | 769 | UInt32 kind = GetEventKind (event); |
|---|
| | 770 | vout_thread_t *p_vout = (vout_thread_t *)userData; |
|---|
| | 771 | |
|---|
| | 772 | result = CallNextEventHandler(nextHandler, event); |
|---|
| | 773 | if(class == kEventClassCommand) |
|---|
| | 774 | { |
|---|
| | 775 | HICommand theHICommand; |
|---|
| | 776 | GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand ); |
|---|
| | 777 | |
|---|
| | 778 | switch ( theHICommand.commandID ) |
|---|
| | 779 | { |
|---|
| | 780 | default: |
|---|
| | 781 | result = eventNotHandledErr; |
|---|
| | 782 | } |
|---|
| | 783 | } |
|---|
| | 784 | else if(class == kEventClassWindow) |
|---|
| | 785 | { |
|---|
| | 786 | WindowRef window; |
|---|
| | 787 | Rect rectPort = {0,0,0,0}; |
|---|
| | 788 | |
|---|
| | 789 | GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window); |
|---|
| | 790 | |
|---|
| | 791 | if(window) |
|---|
| | 792 | { |
|---|
| | 793 | GetPortBounds(GetWindowPort(window), &rectPort); |
|---|
| | 794 | } |
|---|
| | 795 | |
|---|
| | 796 | switch (kind) |
|---|
| | 797 | { |
|---|
| | 798 | case kEventWindowClosed: |
|---|
| | 799 | case kEventWindowZoomed: |
|---|
| | 800 | case kEventWindowBoundsChanged: |
|---|
| | 801 | break; |
|---|
| | 802 | |
|---|
| | 803 | default: |
|---|
| | 804 | result = eventNotHandledErr; |
|---|
| | 805 | } |
|---|
| | 806 | } |
|---|
| | 807 | else if(class == kEventClassMouse) |
|---|
| | 808 | { |
|---|
| | 809 | switch (kind) |
|---|
| | 810 | { |
|---|
| | 811 | case kEventMouseDown: |
|---|
| | 812 | { |
|---|
| | 813 | UInt16 button; |
|---|
| | 814 | |
|---|
| | 815 | GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); |
|---|
| | 816 | switch (button) |
|---|
| | 817 | { |
|---|
| | 818 | case kEventMouseButtonPrimary: |
|---|
| | 819 | { |
|---|
| | 820 | vlc_value_t val; |
|---|
| | 821 | |
|---|
| | 822 | var_Get( p_vout, "mouse-button-down", &val ); |
|---|
| | 823 | val.i_int |= 1; |
|---|
| | 824 | var_Set( p_vout, "mouse-button-down", val ); |
|---|
| | 825 | break; |
|---|
| | 826 | } |
|---|
| | 827 | case kEventMouseButtonSecondary: |
|---|
| | 828 | { |
|---|
| | 829 | vlc_value_t val; |
|---|
| | 830 | |
|---|
| | 831 | var_Get( p_vout, "mouse-button-down", &val ); |
|---|
| | 832 | val.i_int |= 2; |
|---|
| | 833 | var_Set( p_vout, "mouse-button-down", val ); |
|---|
| | 834 | break; |
|---|
| | 835 | } |
|---|
| | 836 | case kEventMouseButtonTertiary: |
|---|
| | 837 | { |
|---|
| | 838 | vlc_value_t val; |
|---|
| | 839 | |
|---|
| | 840 | var_Get( p_vout, "mouse-button-down", &val ); |
|---|
| | 841 | val.i_int |= 4; |
|---|
| | 842 | var_Set( p_vout, "mouse-button-down", val ); |
|---|
| | 843 | break; |
|---|
| | 844 | } |
|---|
| | 845 | default: |
|---|
| | 846 | result = eventNotHandledErr; |
|---|
| | 847 | } |
|---|
| | 848 | break; |
|---|
| | 849 | } |
|---|
| | 850 | |
|---|
| | 851 | case kEventMouseUp: |
|---|
| | 852 | { |
|---|
| | 853 | UInt16 button; |
|---|
| | 854 | |
|---|
| | 855 | GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); |
|---|
| | 856 | switch (button) |
|---|
| | 857 | { |
|---|
| | 858 | case kEventMouseButtonPrimary: |
|---|
| | 859 | { |
|---|
| | 860 | UInt32 clickCount = 0; |
|---|
| | 861 | GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); |
|---|
| | 862 | if( clickCount > 1 ) |
|---|
| | 863 | { |
|---|
| | 864 | vlc_value_t val; |
|---|
| | 865 | |
|---|
| | 866 | val.b_bool = VLC_FALSE; |
|---|
| | 867 | var_Set((vout_thread_t *) p_vout->p_parent, "fullscreen", val); |
|---|
| | 868 | } |
|---|
| | 869 | else |
|---|
| | 870 | { |
|---|
| | 871 | vlc_value_t val; |
|---|
| | 872 | |
|---|
| | 873 | val.b_bool = VLC_TRUE; |
|---|
| | 874 | var_Set( p_vout, "mouse-clicked", val ); |
|---|
| | 875 | |
|---|
| | 876 | var_Get( p_vout, "mouse-button-down", &val ); |
|---|
| | 877 | val.i_int &= ~1; |
|---|
| | 878 | var_Set( p_vout, "mouse-button-down", val ); |
|---|
| | 879 | } |
|---|
| | 880 | break; |
|---|
| | 881 | } |
|---|
| | 882 | case kEventMouseButtonSecondary: |
|---|
| | 883 | { |
|---|
| | 884 | vlc_value_t val; |
|---|
| | 885 | |
|---|
| | 886 | var_Get( p_vout, "mouse-button-down", &val ); |
|---|
| | 887 | val.i_int &= ~2; |
|---|
| | 888 | var_Set( p_vout, "mouse-button-down", val ); |
|---|
| | 889 | break; |
|---|
| | 890 | } |
|---|
| | 891 | case kEventMouseButtonTertiary: |
|---|
| | 892 | { |
|---|
| | 893 | vlc_value_t val; |
|---|
| | 894 | |
|---|
| | 895 | var_Get( p_vout, "mouse-button-down", &val ); |
|---|
| | 896 | val.i_int &= ~2; |
|---|
| | 897 | var_Set( p_vout, "mouse-button-down", val ); |
|---|
| | 898 | break; |
|---|
| | 899 | } |
|---|
| | 900 | default: |
|---|
| | 901 | result = eventNotHandledErr; |
|---|
| | 902 | } |
|---|
| | 903 | break; |
|---|
| | 904 | } |
|---|
| | 905 | |
|---|
| | 906 | case kEventMouseMoved: |
|---|
| | 907 | { |
|---|
| | 908 | Point ml; |
|---|
| | 909 | vlc_value_t val; |
|---|
| | 910 | |
|---|
| | 911 | unsigned int i_x, i_y; |
|---|
| | 912 | unsigned int i_height = p_vout->p_sys->i_height; |
|---|
| | 913 | unsigned int i_width = p_vout->p_sys->i_width; |
|---|
| | 914 | |
|---|
| | 915 | vout_PlacePicture(p_vout, i_width, i_height, &i_x, &i_y, &i_width, &i_height); |
|---|
| | 916 | |
|---|
| | 917 | GetEventParameter(event, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &ml); |
|---|
| | 918 | |
|---|
| | 919 | val.i_int = ( ((int)ml.h) - i_x ) * |
|---|
| | 920 | p_vout->render.i_width / i_width; |
|---|
| | 921 | var_Set( p_vout, "mouse-x", val ); |
|---|
| | 922 | |
|---|
| | 923 | val.i_int = ( ((int)ml.v) - i_y ) * |
|---|
| | 924 | p_vout->render.i_height / i_height; |
|---|
| | 925 | |
|---|
| | 926 | var_Set( p_vout, "mouse-y", val ); |
|---|
| | 927 | |
|---|
| | 928 | val.b_bool = VLC_TRUE; |
|---|
| | 929 | var_Set( p_vout, "mouse-moved", val ); |
|---|
| | 930 | |
|---|
| | 931 | break; |
|---|
| | 932 | } |
|---|
| | 933 | |
|---|
| | 934 | default: |
|---|
| | 935 | result = eventNotHandledErr; |
|---|
| | 936 | } |
|---|
| | 937 | } |
|---|
| | 938 | else if(class == kEventClassTextInput) |
|---|
| | 939 | { |
|---|
| | 940 | switch (kind) |
|---|
| | 941 | { |
|---|
| | 942 | case kEventTextInputUnicodeForKeyEvent: |
|---|
| | 943 | { |
|---|
| | 944 | break; |
|---|
| | 945 | } |
|---|
| | 946 | default: |
|---|
| | 947 | result = eventNotHandledErr; |
|---|
| | 948 | } |
|---|
| | 949 | } |
|---|
| | 950 | else if(class == kEventClassVLCPlugin) |
|---|
| | 951 | { |
|---|
| | 952 | switch (kind) |
|---|
| | 953 | { |
|---|
| | 954 | case kEventVLCPluginShowFullscreen: |
|---|
| | 955 | ShowWindow (p_vout->p_sys->theWindow); |
|---|
| | 956 | SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); |
|---|
| | 957 | //CGDisplayHideCursor(kCGDirectMainDisplay); |
|---|
| | 958 | break; |
|---|
| | 959 | case kEventVLCPluginHideFullscreen: |
|---|
| | 960 | HideWindow (p_vout->p_sys->theWindow); |
|---|
| | 961 | SetSystemUIMode( kUIModeNormal, 0); |
|---|
| | 962 | CGDisplayShowCursor(kCGDirectMainDisplay); |
|---|
| | 963 | break; |
|---|
| | 964 | default: |
|---|
| | 965 | result = eventNotHandledErr; |
|---|
| | 966 | break; |
|---|
| | 967 | } |
|---|
| | 968 | } |
|---|
| | 969 | return result; |
|---|
| | 970 | } |
|---|
| | 971 | |
|---|
| | 972 | static int aglLock( vout_thread_t * p_vout ) |
|---|
| | 973 | { |
|---|
| | 974 | #ifdef __ppc__ |
|---|
| | 975 | /* |
|---|
| | 976 | * before 10.4, we set the AGL context as current and |
|---|
| | 977 | * then we retrieve and use the matching CGL context |
|---|
| | 978 | */ |
|---|
| | 979 | aglSetCurrentContext(p_vout->p_sys->agl_ctx); |
|---|
| | 980 | return kCGLNoError != CGLLockContext( CGLGetCurrentContext() ); |
|---|
| | 981 | #else |
|---|
| | 982 | /* since 10.4, this is the safe way to get the underlying CGL context */ |
|---|
| | 983 | CGLContextObj cglContext; |
|---|
| | 984 | if( aglGetCGLContext(p_vout->p_sys->agl_ctx, (void**)&cglContext) ) |
|---|
| | 985 | { |
|---|
| | 986 | if( kCGLNoError == CGLLockContext( cglContext ) ) |
|---|
| | 987 | { |
|---|
| | 988 | aglSetCurrentContext(p_vout->p_sys->agl_ctx); |
|---|
| | 989 | return 0; |
|---|
| | 990 | } |
|---|
| | 991 | } |
|---|
| | 992 | return 1; |
|---|
| | 993 | #endif |
|---|
| | 994 | } |
|---|
| | 995 | |
|---|
| | 996 | static void aglUnlock( vout_thread_t * p_vout ) |
|---|
| | 997 | { |
|---|
| | 998 | #ifdef __ppc__ |
|---|
| | 999 | /* |
|---|
| | 1000 | * before 10.4, we assume that the AGL context is current. |
|---|
| | 1001 | * therefore, we use the current CGL context |
|---|
| | 1002 | */ |
|---|
| | 1003 | CGLUnlockContext( CGLGetCurrentContext() ); |
|---|
| | 1004 | #else |
|---|
| | 1005 | /* since 10.4, this is the safe way to get the underlying CGL context */ |
|---|
| | 1006 | CGLContextObj cglContext; |
|---|
| | 1007 | if( aglGetCGLContext(p_vout->p_sys->agl_ctx, (void**)&cglContext) ) |
|---|
| | 1008 | { |
|---|
| | 1009 | CGLUnlockContext( cglContext ); |
|---|
| | 1010 | } |
|---|
| | 1011 | #endif |
|---|
| | 1012 | } |
|---|
| | 1013 | |
|---|
| | 1014 | |
|---|