/** * Process an X11 event. */ static int ProcessEvent (vout_display_t *vd, xcb_window_t window, xcb_generic_event_t *ev) { switch (ev->response_type & 0x7f) { case XCB_BUTTON_PRESS: HandleButtonPress (vd, (xcb_button_press_event_t *)ev); break; case XCB_BUTTON_RELEASE: HandleButtonRelease (vd, (xcb_button_release_event_t *)ev); break; case XCB_MOTION_NOTIFY: HandleMotionNotify (vd, (xcb_motion_notify_event_t *)ev); break; case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *cn = (xcb_configure_notify_event_t *)ev; assert (cn->window != window); HandleParentStructure (vd, cn); break; } /* FIXME I am not sure it is the right one */ case XCB_DESTROY_NOTIFY: vout_display_SendEventClose (vd); break; case XCB_MAPPING_NOTIFY: break; default: msg_Dbg (vd, "unhandled event %"PRIu8, ev->response_type); } free (ev); return VLC_SUCCESS; }
/***************************************************************************** * DirectXEventProc: This is the window event processing function. ***************************************************************************** * On Windows, when you create a window you have to attach an event processing * function to it. The aim of this function is to manage "Queued Messages" and * "Nonqueued Messages". * Queued Messages are those picked up and retransmitted by vout_Manage * (using the GetMessage and DispatchMessage functions). * Nonqueued Messages are those that Windows will send directly to this * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...) *****************************************************************************/ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { event_thread_t *p_event; if( message == WM_CREATE ) { /* Store vd for future use */ p_event = (event_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_event ); return TRUE; } else { LONG_PTR p_user_data = GetWindowLongPtr( hwnd, GWLP_USERDATA ); p_event = (event_thread_t *)p_user_data; if( !p_event ) { /* Hmmm mozilla does manage somehow to save the pointer to our * windowproc and still calls it after the vout has been closed. */ return DefWindowProc(hwnd, message, wParam, lParam); } } vout_display_t *vd = p_event->vd; #ifndef UNDER_CE /* Catch the screensaver and the monitor turn-off */ if( message == WM_SYSCOMMAND && ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) ) { //if( vd ) msg_Dbg( vd, "WinProc WM_SYSCOMMAND screensaver" ); return 0; /* this stops them from happening */ } #endif #if 0 if( message == WM_SETCURSOR ) { msg_Err(vd, "WM_SETCURSOR: %d (t2)", p_event->is_cursor_hidden); SetCursor( p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow ); return 1; } #endif if( message == WM_CAPTURECHANGED ) { for( int button = 0; p_event->button_pressed; button++ ) { unsigned m = 1 << button; if( p_event->button_pressed & m ) vout_display_SendEventMouseReleased( p_event->vd, button ); p_event->button_pressed &= ~m; } p_event->button_pressed = 0; return 0; } if( hwnd == p_event->hvideownd ) { #ifdef MODULE_NAME_IS_directx vlc_mutex_lock( &p_event->lock ); const bool use_overlay = p_event->use_overlay; vlc_mutex_unlock( &p_event->lock ); #endif switch( message ) { #ifdef MODULE_NAME_IS_directx case WM_ERASEBKGND: /* For overlay, we need to erase background */ return !use_overlay ? 1 : DefWindowProc(hwnd, message, wParam, lParam); case WM_PAINT: /* ** For overlay, DefWindowProc() will erase dirty regions ** with colorkey. ** For non-overlay, vout will paint the whole window at ** regular interval, therefore dirty regions can be ignored ** to minimize repaint. */ if( !use_overlay ) { ValidateRect(hwnd, NULL); } // fall through to default #else /* ** For OpenGL and Direct3D, vout will update the whole ** window at regular interval, therefore dirty region ** can be ignored to minimize repaint. */ case WM_ERASEBKGND: /* nothing to erase */ return 1; case WM_PAINT: /* nothing to repaint */ ValidateRect(hwnd, NULL); // fall through #endif default: return DefWindowProc(hwnd, message, wParam, lParam); } } switch( message ) { case WM_WINDOWPOSCHANGED: vlc_mutex_lock( &p_event->lock ); p_event->has_moved = true; vlc_mutex_unlock( &p_event->lock ); return 0; /* the user wants to close the window */ case WM_CLOSE: vout_display_SendEventClose(vd); return 0; /* the window has been closed so shut down everything now */ case WM_DESTROY: msg_Dbg( vd, "WinProc WM_DESTROY" ); /* just destroy the window */ PostQuitMessage( 0 ); return 0; case WM_SYSCOMMAND: switch (wParam) { case IDM_TOGGLE_ON_TOP: /* toggle the "on top" status */ { msg_Dbg(vd, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"); HMENU hMenu = GetSystemMenu(vd->sys->hwnd, FALSE); vout_display_SendWindowState(vd, (GetMenuState(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND) & MF_CHECKED) ? VOUT_WINDOW_STATE_NORMAL : VOUT_WINDOW_STATE_ABOVE); return 0; } default: break; } break; case WM_PAINT: case WM_NCPAINT: case WM_ERASEBKGND: return DefWindowProc(hwnd, message, wParam, lParam); case WM_KILLFOCUS: #ifdef MODULE_NAME_IS_wingapi GXSuspend(); #endif #ifdef UNDER_CE if( hwnd == p_event->hfswnd ) { HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); ShowWindow( htbar, SW_SHOW ); } if( !p_event->hparent || hwnd == p_event->hfswnd ) { SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON ); } #endif return 0; case WM_SETFOCUS: #ifdef MODULE_NAME_IS_wingapi GXResume(); #endif #ifdef UNDER_CE /* FIXME vd->cfg is not lock[ed/able] */ #warning "FIXME: race condition" if( p_event->hparent && hwnd != p_event->hfswnd && vd->cfg->is_fullscreen ) vout_display_SendEventFullscreen(vd, false); if( hwnd == p_event->hfswnd ) { HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); ShowWindow( htbar, SW_HIDE ); } if( !p_event->hparent || hwnd == p_event->hfswnd ) { SHFullScreen( hwnd, SHFS_HIDESIPBUTTON ); } #endif return 0; default: //msg_Dbg( vd, "WinProc WM Default %i", message ); break; } /* Let windows handle the message */ return DefWindowProc(hwnd, message, wParam, lParam); }
/** * Proccess pending event */ static void Manage(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; struct caca_event ev; while (caca_get_event(sys->dp, CACA_EVENT_ANY, &ev, 0) > 0) { switch (caca_get_event_type(&ev)) { case CACA_EVENT_KEY_PRESS: { const int caca = caca_get_event_key_ch(&ev); for (int i = 0; keys[i].caca != -1; i++) { if (keys[i].caca == caca) { const int vlc = keys[i].vlc; if (vlc >= 0) vout_display_SendEventKey(vd, vlc); return; } } if (caca >= 0x20 && caca <= 0x7f) { vout_display_SendEventKey(vd, caca); return; } break; } case CACA_EVENT_RESIZE: vout_display_SendEventDisplaySize(vd, caca_get_event_resize_width(&ev), caca_get_event_resize_height(&ev)); break; case CACA_EVENT_MOUSE_MOTION: { vout_display_place_t place; Place(vd, &place); const unsigned x = vd->source.i_x_offset + (int64_t)(caca_get_event_mouse_x(&ev) - place.x) * vd->source.i_visible_width / place.width; const unsigned y = vd->source.i_y_offset + (int64_t)(caca_get_event_mouse_y(&ev) - place.y) * vd->source.i_visible_height / place.height; caca_set_mouse(sys->dp, 1); vout_display_SendEventMouseMoved(vd, x, y); break; } case CACA_EVENT_MOUSE_PRESS: case CACA_EVENT_MOUSE_RELEASE: { caca_set_mouse(sys->dp, 1); const int caca = caca_get_event_mouse_button(&ev); for (int i = 0; mouses[i].caca != -1; i++) { if (mouses[i].caca == caca) { if (caca_get_event_type(&ev) == CACA_EVENT_MOUSE_PRESS) vout_display_SendEventMousePressed(vd, mouses[i].vlc); else vout_display_SendEventMouseReleased(vd, mouses[i].vlc); return; } } break; } case CACA_EVENT_QUIT: vout_display_SendEventClose(vd); break; default: break; } } }
static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) { vout_display_t * vd = WinQueryWindowPtr( hwnd, 0 ); MRESULT result = ( MRESULT )TRUE; if ( !vd ) return WinDefWindowProc( hwnd, msg, mp1, mp2 ); vout_display_sys_t * sys = vd->sys; RECTL rcl; SWP swp; if ( sys->is_mouse_hidden && ((msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) || (msg >= WM_EXTMOUSEFIRST && msg <= WM_EXTMOUSELAST) || msg == WM_MOUSELEAVE)) { WinShowPointer(HWND_DESKTOP, TRUE); sys->is_mouse_hidden = false; } switch( msg ) { /* the user wants to close the window */ case WM_CLOSE: vout_display_SendEventClose(vd); result = 0; break; case WM_MOUSEMOVE : { SHORT i_mouse_x = SHORT1FROMMP( mp1 ); SHORT i_mouse_y = SHORT2FROMMP( mp1 ); RECTL movie_rect; int i_movie_width, i_movie_height; int i_src_width, i_src_height; /* Get a current movie area */ kvaAdjustDstRect( &sys->kvas.rclSrcRect, &movie_rect ); i_movie_width = movie_rect.xRight - movie_rect.xLeft; i_movie_height = movie_rect.yTop - movie_rect.yBottom; i_src_width = sys->kvas.rclSrcRect.xRight - sys->kvas.rclSrcRect.xLeft; i_src_height = sys->kvas.rclSrcRect.yBottom - sys->kvas.rclSrcRect.yTop; int x = ( i_mouse_x - movie_rect.xLeft ) * i_src_width / i_movie_width + sys->kvas.rclSrcRect.xLeft; int y = ( i_mouse_y - movie_rect.yBottom ) * i_src_height / i_movie_height; /* Invert Y coordinate and add y offset */ y = ( i_src_height - y ) + sys->kvas.rclSrcRect.yTop;; vout_display_SendEventMouseMoved(vd, x, y); result = WinDefWindowProc( hwnd, msg, mp1,mp2 ); break; } case WM_BUTTON1DOWN : MousePressed( vd, hwnd, MOUSE_BUTTON_LEFT ); break; case WM_BUTTON2DOWN : MousePressed( vd, hwnd, MOUSE_BUTTON_RIGHT ); break; case WM_BUTTON3DOWN : MousePressed( vd, hwnd, MOUSE_BUTTON_CENTER ); break; case WM_BUTTON1UP : MouseReleased( vd, MOUSE_BUTTON_LEFT ); break; case WM_BUTTON2UP : MouseReleased( vd, MOUSE_BUTTON_RIGHT ); break; case WM_BUTTON3UP : MouseReleased( vd, MOUSE_BUTTON_CENTER ); break; case WM_BUTTON1DBLCLK : vout_display_SendEventMouseDoubleClick(vd); break; case WM_TRANSLATEACCEL : /* We have no accelerator table at all */ result = ( MRESULT )FALSE; break; case WM_CHAR : { USHORT i_flags = SHORT1FROMMP( mp1 ); USHORT i_ch = SHORT1FROMMP( mp2 ); USHORT i_vk = SHORT2FROMMP( mp2 ); int i_key = 0; /* If embedded window, let the parent process keys */ if( sys->parent_window ) { WinPostMsg( sys->parent, msg, mp1, mp2 ); break; } if( !( i_flags & KC_KEYUP )) { if( i_flags & KC_VIRTUALKEY ) /* convert the key if possible */ i_key = ConvertKey( i_vk ); else if(( i_flags & KC_CHAR ) && !HIBYTE( i_ch )) i_key = tolower( i_ch ); if( i_key ) { if( i_flags & KC_SHIFT ) i_key |= KEY_MODIFIER_SHIFT; if( i_flags & KC_CTRL ) i_key |= KEY_MODIFIER_CTRL; if( i_flags & KC_ALT ) i_key |= KEY_MODIFIER_ALT; vout_display_SendEventKey(vd, i_key); } } break; } /* Process Manage() call */ case WM_VLC_MANAGE : break; /* Fullscreen change */ case WM_VLC_FULLSCREEN_CHANGE : if( LONGFROMMP( mp1 )) { WinQueryWindowPos( sys->frame, &swp ); sys->client_rect.xLeft = swp.x; sys->client_rect.yBottom = swp.y; sys->client_rect.xRight = sys->client_rect.xLeft + swp.cx; sys->client_rect.yTop = sys->client_rect.yBottom + swp.cy; WinCalcFrameRect( sys->frame, &sys->client_rect, TRUE ); rcl.xLeft = 0; rcl.yBottom = 0; rcl.xRight = sys->i_screen_width; rcl.yTop = sys->i_screen_height; } else rcl = sys->client_rect; WinCalcFrameRect( sys->frame, &rcl, FALSE ); WinSetWindowPos( sys->frame, HWND_TOP, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE ); break; /* Size change */ case WM_VLC_SIZE_CHANGE : rcl.xLeft = 0; rcl.yBottom = 0; rcl.xRight = LONGFROMMP( mp1 ); rcl.yTop = LONGFROMMP( mp2 ); WinCalcFrameRect( sys->frame, &rcl, FALSE ); WinSetWindowPos( sys->frame, NULLHANDLE, 0, 0, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_SIZE ); WinQueryWindowPos( sys->frame, &swp ); sys->client_rect.xLeft = swp.x; sys->client_rect.yBottom = swp.y; sys->client_rect.xRight = sys->client_rect.xLeft + swp.cx; sys->client_rect.yTop = sys->client_rect.yBottom + swp.cy; WinCalcFrameRect( sys->frame, &sys->client_rect, TRUE ); break; default : return WinDefWindowProc( hwnd, msg, mp1, mp2 ); } /* If embedded window, we need to change our window size according to a * parent window size */ if( sys->parent_window ) { WinQueryWindowRect( sys->parent, &rcl ); if( rcl.xLeft != sys->parent_rect.xLeft || rcl.yBottom != sys->parent_rect.yBottom || rcl.xRight != sys->parent_rect.xRight || rcl.yTop != sys->parent_rect.yTop) { sys->parent_rect = rcl; WinCalcFrameRect( sys->frame, &rcl, FALSE ); WinSetWindowPos( sys->frame, NULLHANDLE, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_SIZE | SWP_MOVE ); } } return result; }
/***************************************************************************** * WinVoutEventProc: This is the window event processing function. ***************************************************************************** * On Windows, when you create a window you have to attach an event processing * function to it. The aim of this function is to manage "Queued Messages" and * "Nonqueued Messages". * Queued Messages are those picked up and retransmitted by vout_Manage * (using the GetMessage and DispatchMessage functions). * Nonqueued Messages are those that Windows will send directly to this * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...) *****************************************************************************/ static long FAR PASCAL WinVoutEventProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { event_thread_t *p_event; if( message == WM_CREATE ) { /* Store vd for future use */ p_event = (event_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_event ); return TRUE; } else { LONG_PTR p_user_data = GetWindowLongPtr( hwnd, GWLP_USERDATA ); p_event = (event_thread_t *)p_user_data; if( !p_event ) { /* Hmmm mozilla does manage somehow to save the pointer to our * windowproc and still calls it after the vout has been closed. */ return DefWindowProc(hwnd, message, wParam, lParam); } } vout_display_t *vd = p_event->vd; #if 0 if( message == WM_SETCURSOR ) { msg_Err(vd, "WM_SETCURSOR: %d (t2)", p_event->is_cursor_hidden); SetCursor( p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow ); return 1; } #endif if( message == WM_CAPTURECHANGED ) { for( int button = 0; p_event->button_pressed; button++ ) { unsigned m = 1 << button; if( p_event->button_pressed & m ) vout_display_SendEventMouseReleased( p_event->vd, button ); p_event->button_pressed &= ~m; } p_event->button_pressed = 0; return 0; } if( hwnd == p_event->hvideownd ) { #ifdef MODULE_NAME_IS_directdraw vlc_mutex_lock( &p_event->lock ); const bool use_overlay = p_event->use_overlay; vlc_mutex_unlock( &p_event->lock ); #endif switch( message ) { #ifdef MODULE_NAME_IS_directdraw case WM_ERASEBKGND: /* For overlay, we need to erase background */ return !use_overlay ? 1 : DefWindowProc(hwnd, message, wParam, lParam); case WM_PAINT: /* ** For overlay, DefWindowProc() will erase dirty regions ** with colorkey. ** For non-overlay, vout will paint the whole window at ** regular interval, therefore dirty regions can be ignored ** to minimize repaint. */ if( !use_overlay ) { ValidateRect(hwnd, NULL); } // fall through to default #else /* ** For OpenGL and Direct3D, vout will update the whole ** window at regular interval, therefore dirty region ** can be ignored to minimize repaint. */ case WM_ERASEBKGND: /* nothing to erase */ return 1; case WM_PAINT: /* nothing to repaint */ ValidateRect(hwnd, NULL); // fall through #endif default: return DefWindowProc(hwnd, message, wParam, lParam); } } switch( message ) { case WM_WINDOWPOSCHANGED: atomic_store(&p_event->has_moved, true); return 0; /* the user wants to close the window */ case WM_CLOSE: vout_display_SendEventClose(vd); return 0; /* the window has been closed so shut down everything now */ case WM_DESTROY: msg_Dbg( vd, "WinProc WM_DESTROY" ); /* just destroy the window */ PostQuitMessage( 0 ); return 0; case WM_SYSCOMMAND: switch (wParam) { case IDM_TOGGLE_ON_TOP: /* toggle the "on top" status */ { msg_Dbg(vd, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"); HMENU hMenu = GetSystemMenu(vd->sys->hwnd, FALSE); vout_display_SendWindowState(vd, (GetMenuState(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND) & MF_CHECKED) ? VOUT_WINDOW_STATE_NORMAL : VOUT_WINDOW_STATE_ABOVE); return 0; } default: break; } break; case WM_PAINT: case WM_NCPAINT: case WM_ERASEBKGND: return DefWindowProc(hwnd, message, wParam, lParam); case WM_KILLFOCUS: return 0; case WM_SETFOCUS: return 0; case WM_GESTURE: return DecodeGesture( VLC_OBJECT(vd), p_event->p_gesture, hwnd, message, wParam, lParam ); default: //msg_Dbg( vd, "WinProc WM Default %i", message ); break; } /* Let windows handle the message */ return DefWindowProc(hwnd, message, wParam, lParam); }