📄 xcommon.c
字号:
} p_vout->p_sys->last_date = last_date; p_pic->b_force = 1; p_pic->p_sys->nb_display = 1; vlc_mutex_unlock( &p_vout->picture_lock ); } else { p_pic->p_sys->nb_display = 0; p_pic->b_force = 0; } } xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );#endif#ifdef HAVE_SYS_SHM_H if( p_vout->p_sys->i_shm_opcode ) { /* Display rendered image using shared memory extension */# if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc) XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset, p_vout->fmt_out.i_visible_width, p_vout->fmt_out.i_visible_height, 0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height, False /* Don't put True here or you'll waste your CPU */ );# else XShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset, 0 /*dest_x*/, 0 /*dest_y*/, p_vout->fmt_out.i_visible_width, p_vout->fmt_out.i_visible_height, False /* Don't put True here ! */ );# endif } else#endif /* HAVE_SYS_SHM_H */ { /* Use standard XPutImage -- this is gonna be slow ! */#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc) XvPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset, p_vout->fmt_out.i_visible_width, p_vout->fmt_out.i_visible_height, 0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height );#else XPutImage( p_vout->p_sys->p_display, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset, 0 /*dest_x*/, 0 /*dest_y*/, p_vout->fmt_out.i_visible_width, p_vout->fmt_out.i_visible_height );#endif } /* Make sure the command is sent now - do NOT use XFlush !*/ XSync( p_vout->p_sys->p_display, False ); vlc_mutex_unlock( &p_vout->p_sys->lock );}/***************************************************************************** * ManageVideo: handle X11 events ***************************************************************************** * This function should be called regularly by video output thread. It manages * X11 events and allows window resizing. It returns a non null value on * error. *****************************************************************************/static int ManageVideo( vout_thread_t *p_vout ){ XEvent xevent; /* X11 event */ vlc_value_t val; vlc_mutex_lock( &p_vout->p_sys->lock );#ifdef MODULE_NAME_IS_xvmc xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );#endif /* Handle events from the owner window */ if( p_vout->p_sys->p_win->owner_window ) { while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->p_win->owner_window, StructureNotifyMask, &xevent ) == True ) { /* ConfigureNotify event: prepare */ if( xevent.type == ConfigureNotify ) { /* Update dimensions */ XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->p_win->base_window, xevent.xconfigure.width, xevent.xconfigure.height ); } } } /* Handle X11 events: ConfigureNotify events are parsed to know if the * output window's size changed, MapNotify and UnmapNotify to know if the * window is mapped (and if the display is useful), and ClientMessages * to intercept window destruction requests */ while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->p_win->base_window, StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | Button1MotionMask , &xevent ) == True ) { /* ConfigureNotify event: prepare */ if( xevent.type == ConfigureNotify ) { if( (unsigned int)xevent.xconfigure.width != p_vout->p_sys->p_win->i_width || (unsigned int)xevent.xconfigure.height != p_vout->p_sys->p_win->i_height ) { /* Update dimensions */ p_vout->i_changes |= VOUT_SIZE_CHANGE; p_vout->p_sys->p_win->i_width = xevent.xconfigure.width; p_vout->p_sys->p_win->i_height = xevent.xconfigure.height; } } /* Keyboard event */ else if( xevent.type == KeyPress ) { unsigned int state = xevent.xkey.state; KeySym x_key_symbol; char i_key; /* ISO Latin-1 key */ /* We may have keys like F1 trough F12, ESC ... */ x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display, xevent.xkey.keycode, 0 ); val.i_int = ConvertKey( (int)x_key_symbol ); xevent.xkey.state &= ~ShiftMask; xevent.xkey.state &= ~ControlMask; xevent.xkey.state &= ~Mod1Mask; if( !val.i_int && XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) { /* "Normal Keys" * The reason why I use this instead of XK_0 is that * with XLookupString, we don't have to care about * keymaps. */ val.i_int = i_key; } if( val.i_int ) { if( state & ShiftMask ) { val.i_int |= KEY_MODIFIER_SHIFT; } if( state & ControlMask ) { val.i_int |= KEY_MODIFIER_CTRL; } if( state & Mod1Mask ) { val.i_int |= KEY_MODIFIER_ALT; } var_Set( p_vout->p_libvlc, "key-pressed", val ); } } /* Mouse click */ else if( xevent.type == ButtonPress ) { switch( ((XButtonEvent *)&xevent)->button ) { case Button1: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 1; var_Set( p_vout, "mouse-button-down", val ); /* detect double-clicks */ if( ( ((XButtonEvent *)&xevent)->time - p_vout->p_sys->i_time_button_last_pressed ) < 300 ) { p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; } p_vout->p_sys->i_time_button_last_pressed = ((XButtonEvent *)&xevent)->time; break; case Button2: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 2; var_Set( p_vout, "mouse-button-down", val ); break; case Button3: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 4; var_Set( p_vout, "mouse-button-down", val ); break; case Button4: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 8; var_Set( p_vout, "mouse-button-down", val ); break; case Button5: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 16; var_Set( p_vout, "mouse-button-down", val ); break; } } /* Mouse release */ else if( xevent.type == ButtonRelease ) { switch( ((XButtonEvent *)&xevent)->button ) { case Button1: { var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~1; var_Set( p_vout, "mouse-button-down", val ); val.b_bool = true; var_Set( p_vout, "mouse-clicked", val ); vlc_value_t val; val.b_bool = false; var_Set( p_vout->p_libvlc, "intf-popupmenu", val ); } break; case Button2: { var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~2; var_Set( p_vout, "mouse-button-down", val ); var_Get( p_vout->p_libvlc, "intf-show", &val ); val.b_bool = !val.b_bool; var_Set( p_vout->p_libvlc, "intf-show", val ); } break; case Button3: { intf_thread_t *p_intf; var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~4; var_Set( p_vout, "mouse-button-down", val ); p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF, FIND_ANYWHERE ); if( p_intf ) { p_intf->b_menu_change = 1; vlc_object_release( p_intf ); } vlc_value_t val; val.b_bool = true; var_Set( p_vout->p_libvlc, "intf-popupmenu", val ); } break; case Button4: var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~8; var_Set( p_vout, "mouse-button-down", val ); break; case Button5: var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~16; var_Set( p_vout, "mouse-button-down", val ); break; } } /* Mouse move */ else if( xevent.type == MotionNotify ) { unsigned int i_width, i_height, i_x, i_y; vlc_value_t val; /* somewhat different use for vout_PlacePicture: * here the values are needed to give to mouse coordinates * in the original picture space */ vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width, p_vout->p_sys->p_win->i_height, &i_x, &i_y, &i_width, &i_height ); /* Compute the x coordinate and check if the value is in [0,p_vout->fmt_in.i_visible_width] */ val.i_int = ( xevent.xmotion.x - i_x ) * p_vout->fmt_in.i_visible_width / i_width + p_vout->fmt_in.i_x_offset; if( (int)(xevent.xmotion.x - i_x) < 0 ) val.i_int = 0; else if( (unsigned int)val.i_int > p_vout->fmt_in.i_visible_width ) val.i_int = p_vout->fmt_in.i_visible_width; var_Set( p_vout, "mouse-x", val ); /* compute the y coordinate and check if the value is in [0,p_vout->fmt_in.i_visible_height] */ val.i_int = ( xevent.xmotion.y - i_y ) * p_vout->fmt_in.i_visible_height / i_height + p_vout->fmt_in.i_y_offset; if( (int)(xevent.xmotion.y - i_y) < 0 ) val.i_int = 0; else if( (unsigned int)val.i_int > p_vout->fmt_in.i_visible_height ) val.i_int = p_vout->fmt_in.i_visible_height; var_Set( p_vout, "mouse-y", val ); val.b_bool = true; var_Set( p_vout, "mouse-moved", val ); p_vout->p_sys->i_time_mouse_last_moved = mdate(); if( ! p_vout->p_sys->b_mouse_pointer_visible ) { ToggleCursor( p_vout ); } } else if( xevent.type == ReparentNotify /* XXX: why do we get this? */ || xevent.type == MapNotify || xevent.type == UnmapNotify ) { /* Ignore these events */ } else /* Other events */ { msg_Warn( p_vout, "unhandled event %d received", xevent.type ); } } /* Handle events for video output sub-window */ while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->p_win->video_window, ExposureMask, &xevent ) == True ) { /* Window exposed (only handled if stream playback is paused) */ if( xevent.type == Expose )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -