void X11Factory::getMonitorInfo( const GenericWindow &rWindow, int* p_x, int* p_y, int* p_width, int* p_height ) const { // initialize to default geometry *p_x = 0; *p_y = 0; *p_width = getScreenWidth(); *p_height = getScreenHeight(); // Use Xinerama to determine the monitor where the video // mostly resides (biggest surface) Display *pDisplay = m_pDisplay->getDisplay(); Window wnd = (Window)rWindow.getOSHandle(); Window root = DefaultRootWindow( pDisplay ); Window child_wnd; int x, y; unsigned int w, h, border, depth; XGetGeometry( pDisplay, wnd, &root, &x, &y, &w, &h, &border, &depth ); XTranslateCoordinates( pDisplay, wnd, root, 0, 0, &x, &y, &child_wnd ); int num; XineramaScreenInfo* info = XineramaQueryScreens( pDisplay, &num ); if( info ) { Region reg1 = XCreateRegion(); XRectangle rect1 = { (short)x, (short)y, (unsigned short)w, (unsigned short)h }; XUnionRectWithRegion( &rect1, reg1, reg1 ); unsigned int surface = 0; for( int i = 0; i < num; i++ ) { Region reg2 = XCreateRegion(); XRectangle rect2 = { info[i].x_org, info[i].y_org, (unsigned short)info[i].width, (unsigned short)info[i].height }; XUnionRectWithRegion( &rect2, reg2, reg2 ); Region reg = XCreateRegion(); XIntersectRegion( reg1, reg2, reg ); XRectangle rect; XClipBox( reg, &rect ); unsigned int surf = rect.width * rect.height; if( surf > surface ) { surface = surf; *p_x = info[i].x_org; *p_y = info[i].y_org; *p_width = info[i].width; *p_height = info[i].height; } XDestroyRegion( reg ); XDestroyRegion( reg2 ); } XDestroyRegion( reg1 ); XFree( info ); } }
static pascal OSStatus WinEventHandler( EventHandlerCallRef handler, EventRef event, void *data ) { GenericWindow *pWin = (GenericWindow*)data; intf_thread_t *pIntf = pWin->getIntf(); //fprintf(stderr, "event\n" ); UInt32 evclass = GetEventClass( event ); UInt32 evkind = GetEventKind( event ); switch( evclass ) { case kEventClassWindow: EvtRefresh evt( pIntf, 0, 0, -1, -1); pWin->processEvent( evt ); break; } }
// static INT_PTR GenericWindow::_dlgProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { GenericWindow *pThis = NULL; if (msg == WM_INITDIALOG) { // map dialog window handle to its GenericWindow object pThis = (GenericWindow *) lParam; ::SetWindowLongPtr ( hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)pThis); pThis->m_hWnd = hWnd; } else { // get window object from window handle LONG_PTR ptr = ::GetWindowLongPtr (hWnd, GWLP_USERDATA); pThis = (GenericWindow *) ptr; } if (pThis) { return pThis->HandleDialogMessage (msg, wParam, lParam); } return FALSE; }
// static LRESULT CALLBACK GenericWindow::_wndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { GenericWindow *pWnd = NULL; if (msg == WM_CREATE) { // get GenericWindow object CREATESTRUCT *cs = (CREATESTRUCT *) lParam; pWnd = (GenericWindow *)cs->lpCreateParams; WINGUI_ASSERT (pWnd); // bind HWND with the Sim8085IdeWindow object ::SetWindowLongPtr ( hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)pWnd); } else { // get window object from window handle LONG_PTR ptr = ::GetWindowLongPtr (hWnd, GWLP_USERDATA); pWnd = (GenericWindow *) ptr; } if (pWnd) { return pWnd->HandleMessage (msg, wParam, lParam); } return ::DefWindowProc (hWnd, msg, wParam, lParam); }
void Win32Factory::getMonitorInfo( const GenericWindow &rWindow, int* p_x, int* p_y, int* p_width, int* p_height ) const { HWND wnd = (HWND)rWindow.getOSHandle(); HMONITOR hmon = MonitorFromWindow( wnd, MONITOR_DEFAULTTONEAREST ); MONITORINFO mi; mi.cbSize = sizeof( MONITORINFO ); if( hmon && GetMonitorInfo( hmon, &mi ) ) { *p_x = mi.rcMonitor.left; *p_y = mi.rcMonitor.top; *p_width = mi.rcMonitor.right - mi.rcMonitor.left; *p_height = mi.rcMonitor.bottom - mi.rcMonitor.top; } else { *p_x = 0; *p_y = 0; *p_width = getScreenWidth(); *p_height = getScreenHeight(); } }
X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow, X11Display &rDisplay, bool dragDrop, bool playOnDrop, X11Window *pParentWindow, GenericWindow::WindowType_t type ): OSWindow( pIntf ), m_rDisplay( rDisplay ), m_pParent( pParentWindow ), m_dragDrop( dragDrop ), m_pDropTarget( NULL ), m_type ( type ) { XSetWindowAttributes attr; unsigned long valuemask; std::string name_type; if( type == GenericWindow::FullscreenWindow ) { m_wnd_parent = DefaultRootWindow( XDISPLAY ); int i_screen = DefaultScreen( XDISPLAY ); attr.event_mask = ExposureMask | StructureNotifyMask; attr.background_pixel = BlackPixel( XDISPLAY, i_screen ); attr.backing_store = Always; valuemask = CWBackingStore | CWBackPixel | CWEventMask; if( NET_WM_STATE_FULLSCREEN == None ) { attr.override_redirect = True; valuemask = valuemask | CWOverrideRedirect; } name_type = "Fullscreen"; } else if( type == GenericWindow::VoutWindow ) { m_wnd_parent = pParentWindow->m_wnd; int i_screen = DefaultScreen( XDISPLAY ); attr.event_mask = ExposureMask | StructureNotifyMask; attr.backing_store = Always; attr.background_pixel = BlackPixel( XDISPLAY, i_screen ); valuemask = CWBackingStore | CWBackPixel | CWEventMask; name_type = "VoutWindow"; } else if( type == GenericWindow::FscWindow ) { m_wnd_parent = DefaultRootWindow( XDISPLAY ); attr.event_mask = ExposureMask | StructureNotifyMask; valuemask = CWEventMask; name_type = "FscWindow"; } else { m_wnd_parent = DefaultRootWindow( XDISPLAY ); attr.event_mask = ExposureMask | StructureNotifyMask; valuemask = CWEventMask; name_type = "TopWindow"; } // Create the window m_wnd = XCreateWindow( XDISPLAY, m_wnd_parent, -10, 0, 10, 10, 0, 0, InputOutput, CopyFromParent, valuemask, &attr ); // wait for X server to process the previous commands XSync( XDISPLAY, false ); // Set the colormap for 8bpp mode if( XPIXELSIZE == 1 ) { XSetWindowColormap( XDISPLAY, m_wnd, m_rDisplay.getColormap() ); } // Select events received by the window long event_mask; if( type == GenericWindow::VoutWindow ) { event_mask = ExposureMask|KeyPressMask| LeaveWindowMask|FocusChangeMask; } else { event_mask = ExposureMask|KeyPressMask| PointerMotionMask|ButtonPressMask|ButtonReleaseMask| LeaveWindowMask|FocusChangeMask; } XSelectInput( XDISPLAY, m_wnd, event_mask ); // Store a pointer on the generic window in a map X11Factory *pFactory = (X11Factory*)X11Factory::instance( getIntf() ); pFactory->m_windowMap[m_wnd] = &rWindow; // Changing decorations struct { unsigned long flags; unsigned long functions; unsigned long decorations; signed long input_mode; unsigned long status; } motifWmHints; Atom hints_atom = XInternAtom( XDISPLAY, "_MOTIF_WM_HINTS", False ); motifWmHints.flags = 2; // MWM_HINTS_DECORATIONS; motifWmHints.decorations = 0; XChangeProperty( XDISPLAY, m_wnd, hints_atom, hints_atom, 32, PropModeReplace, (unsigned char *)&motifWmHints, sizeof( motifWmHints ) / sizeof( uint32_t ) ); // Drag & drop if( m_dragDrop ) { // Create a Dnd object for this window m_pDropTarget = new X11DragDrop( getIntf(), m_rDisplay, m_wnd, playOnDrop, &rWindow ); // Register the window as a drop target Atom xdndAtom = XInternAtom( XDISPLAY, "XdndAware", False ); char xdndVersion = 4; XChangeProperty( XDISPLAY, m_wnd, xdndAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&xdndVersion, 1 ); // Store a pointer to be used in X11Loop pFactory->m_dndMap[m_wnd] = m_pDropTarget; } // Change the window title std::string name_window = "VLC (" + name_type + ")"; XStoreName( XDISPLAY, m_wnd, name_window.c_str() ); // Set the WM_TRANSIENT_FOR property if( type == GenericWindow::FscWindow ) { // Associate the fsc window to the fullscreen window VoutManager* pVoutManager = VoutManager::instance( getIntf() ); GenericWindow* pWin = pVoutManager->getVoutMainWindow(); Window wnd = (Window) pWin->getOSHandle(); XSetTransientForHint( XDISPLAY, m_wnd, wnd ); } else { // Associate the regular top-level window to the offscren main window XSetTransientForHint( XDISPLAY, m_wnd, m_rDisplay.getMainWindow() ); } // initialize Class Hint XClassHint classhint; classhint.res_name = (char*) "vlc"; classhint.res_class = (char*) "Vlc"; XSetClassHint( XDISPLAY, m_wnd, &classhint ); // copies WM_HINTS from the main window XWMHints *wm = XGetWMHints( XDISPLAY, m_rDisplay.getMainWindow() ); if( wm ) { XSetWMHints( XDISPLAY, m_wnd, wm ); XFree( wm ); } // initialize WM_CLIENT_MACHINE char* hostname = NULL; long host_name_max = sysconf( _SC_HOST_NAME_MAX ); if( host_name_max <= 0 ) host_name_max = _POSIX_HOST_NAME_MAX; hostname = new char[host_name_max]; if( hostname && gethostname( hostname, host_name_max ) == 0 ) { hostname[host_name_max - 1] = '\0'; XTextProperty textprop; textprop.value = (unsigned char *) hostname; textprop.encoding = XA_STRING; textprop.format = 8; textprop.nitems = strlen( hostname ); XSetWMClientMachine( XDISPLAY, m_wnd, &textprop); } delete[] hostname; // initialize EWMH pid pid_t pid = getpid(); assert( NET_WM_PID != None ); XChangeProperty( XDISPLAY, m_wnd, NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1 ); }
void X11Loop::handleX11Event() { XEvent event; OSFactory *pOsFactory = OSFactory::instance( getIntf() ); // Look for the next event in the queue XNextEvent( XDISPLAY, &event ); if( event.xany.window == m_rDisplay.getMainWindow() ) { if( event.type == MapNotify ) { // When the "parent" window is mapped, show all the visible // windows, as it is not automatic, unfortunately Theme *pTheme = getIntf()->p_sys->p_theme; if( pTheme ) { // Commented out as it really doesn't seem useful // but rather brings visible problems // pTheme->getWindowManager().synchVisibility(); } } return; } // Find the window to which the event is sent GenericWindow *pWin = ((X11Factory*)pOsFactory)->m_windowMap[event.xany.window]; if( !pWin ) { return; } // Send the right event object to the window switch( event.type ) { case Expose: { EvtRefresh evt( getIntf(), event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height ); pWin->processEvent( evt ); break; } case FocusIn: { EvtFocus evt( getIntf(), true ); pWin->processEvent( evt ); break; } case FocusOut: { EvtFocus evt( getIntf(), false ); pWin->processEvent( evt ); break; } case MotionNotify: { // Don't trust the position in the event, it is // out of date. Get the actual current position instead int x, y; pOsFactory->getMousePos( x, y ); EvtMotion evt( getIntf(), x, y ); pWin->processEvent( evt ); break; } case LeaveNotify: { EvtLeave evt( getIntf() ); pWin->processEvent( evt ); break; } case ButtonPress: case ButtonRelease: { EvtMouse::ActionType_t action = EvtMouse::kDown; switch( event.type ) { case ButtonPress: action = EvtMouse::kDown; break; case ButtonRelease: action = EvtMouse::kUp; break; } // Get the modifiers int mod = EvtInput::kModNone; if( event.xbutton.state & Mod1Mask ) { mod |= EvtInput::kModAlt; } if( event.xbutton.state & ControlMask ) { mod |= EvtInput::kModCtrl; } if( event.xbutton.state & ShiftMask ) { mod |= EvtInput::kModShift; } // Check for double clicks if( event.type == ButtonPress && event.xbutton.button == 1 ) { mtime_t time = mdate(); int x, y; pOsFactory->getMousePos( x, y ); if( time - m_lastClickTime < m_dblClickDelay && x == m_lastClickPosX && y == m_lastClickPosY ) { m_lastClickTime = 0; action = EvtMouse::kDblClick; } else { m_lastClickTime = time; m_lastClickPosX = x; m_lastClickPosY = y; } } switch( event.xbutton.button ) { case 1: { EvtMouse evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtMouse::kLeft, action, mod ); pWin->processEvent( evt ); break; } case 2: { EvtMouse evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtMouse::kMiddle, action, mod ); pWin->processEvent( evt ); break; } case 3: { EvtMouse evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtMouse::kRight, action, mod ); pWin->processEvent( evt ); break; } case 4: { // Scroll up EvtScroll evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtScroll::kUp, mod ); pWin->processEvent( evt ); break; } case 5: { // Scroll down EvtScroll evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtScroll::kDown, mod ); pWin->processEvent( evt ); break; } } break; } case KeyPress: case KeyRelease: { EvtKey::ActionType_t action = EvtKey::kDown; int mod = EvtInput::kModNone; // Get the modifiers if( event.xkey.state & Mod1Mask ) { mod |= EvtInput::kModAlt; } if( event.xkey.state & ControlMask ) { mod |= EvtInput::kModCtrl; } if( event.xkey.state & ShiftMask ) { mod |= EvtInput::kModShift; } // Take the first keysym = lower case character KeySym keysym = XLookupKeysym( &event.xkey, 0 ); // Get VLC key code from the keysym int key = keysymToVlcKey[keysym]; if( !key ) { // Normal key key = keysym; } switch( event.type ) { case KeyPress: action = EvtKey::kDown; break; case KeyRelease: action = EvtKey::kUp; break; } EvtKey evt( getIntf(), key, action, mod ); pWin->processEvent( evt ); break; } case ClientMessage: { // Get the message type string type = XGetAtomName( XDISPLAY, event.xclient.message_type ); // Find the DnD object for this window X11DragDrop *pDnd = ((X11Factory*)pOsFactory)->m_dndMap[event.xany.window]; if( !pDnd ) { msg_Err( getIntf(), "no associated D&D object" ); return; } if( type == "XdndEnter" ) { pDnd->dndEnter( event.xclient.data.l ); } else if( type == "XdndPosition" ) { pDnd->dndPosition( event.xclient.data.l ); } else if( type == "XdndLeave" ) { pDnd->dndLeave( event.xclient.data.l ); } else if( type == "XdndDrop" ) { pDnd->dndDrop( event.xclient.data.l ); } break; } } }
void X11Loop::handleX11Event() { XEvent event; OSFactory *pOsFactory = OSFactory::instance( getIntf() ); // Look for the next event in the queue XNextEvent( XDISPLAY, &event ); if( event.xany.window == m_rDisplay.getMainWindow() ) { if( event.type == ClientMessage ) { Atom wm_protocols = XInternAtom( XDISPLAY, "WM_PROTOCOLS", False); Atom wm_delete = XInternAtom( XDISPLAY, "WM_DELETE_WINDOW", False); if( event.xclient.message_type == wm_protocols && event.xclient.data.l[0] == wm_delete ) { msg_Dbg( getIntf(), "Received WM_DELETE_WINDOW message" ); libvlc_Quit( getIntf()->p_libvlc ); } } return; } // Find the window to which the event is sent GenericWindow *pWin = ((X11Factory*)pOsFactory)->m_windowMap[event.xany.window]; if( !pWin ) { return; } // Send the right event object to the window switch( event.type ) { case Expose: { EvtRefresh evt( getIntf(), event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height ); pWin->processEvent( evt ); break; } case FocusIn: { EvtFocus evt( getIntf(), true ); pWin->processEvent( evt ); break; } case FocusOut: { EvtFocus evt( getIntf(), false ); pWin->processEvent( evt ); break; } case MotionNotify: { // Don't trust the position in the event, it is // out of date. Get the actual current position instead int x, y; pOsFactory->getMousePos( x, y ); EvtMotion evt( getIntf(), x, y ); pWin->processEvent( evt ); break; } case LeaveNotify: { EvtLeave evt( getIntf() ); pWin->processEvent( evt ); break; } case ButtonPress: case ButtonRelease: { EvtMouse::ActionType_t action = EvtMouse::kDown; switch( event.type ) { case ButtonPress: action = EvtMouse::kDown; break; case ButtonRelease: action = EvtMouse::kUp; break; } int mod = X11ModToMod( event.xbutton.state ); // Check for double clicks if( event.type == ButtonPress && event.xbutton.button == 1 ) { mtime_t time = mdate(); int x, y; pOsFactory->getMousePos( x, y ); if( time - m_lastClickTime < m_dblClickDelay && x == m_lastClickPosX && y == m_lastClickPosY ) { m_lastClickTime = 0; action = EvtMouse::kDblClick; } else { m_lastClickTime = time; m_lastClickPosX = x; m_lastClickPosY = y; } } switch( event.xbutton.button ) { case 1: { EvtMouse evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtMouse::kLeft, action, mod ); pWin->processEvent( evt ); break; } case 2: { EvtMouse evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtMouse::kMiddle, action, mod ); pWin->processEvent( evt ); break; } case 3: { EvtMouse evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtMouse::kRight, action, mod ); pWin->processEvent( evt ); break; } case 4: { // Scroll up EvtScroll evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtScroll::kUp, mod ); pWin->processEvent( evt ); break; } case 5: { // Scroll down EvtScroll evt( getIntf(), event.xbutton.x, event.xbutton.y, EvtScroll::kDown, mod ); pWin->processEvent( evt ); break; } } break; } case KeyPress: case KeyRelease: { // Take the first keysym = lower case character, and translate. int key = keysymToVlcKey( XLookupKeysym( &event.xkey, 0 ) ); EvtKey evt( getIntf(), key, event.type==KeyRelease ? EvtKey::kUp : EvtKey::kDown, X11ModToMod( event.xkey.state ) ); pWin->processEvent( evt ); break; } case ClientMessage: { // Get the message type string type = XGetAtomName( XDISPLAY, event.xclient.message_type ); // Find the DnD object for this window X11DragDrop *pDnd = ((X11Factory*)pOsFactory)->m_dndMap[event.xany.window]; if( !pDnd ) { msg_Err( getIntf(), "no associated D&D object" ); return; } if( type == "XdndEnter" ) pDnd->dndEnter( event.xclient.data.l ); else if( type == "XdndPosition" ) pDnd->dndPosition( event.xclient.data.l ); else if( type == "XdndLeave" ) pDnd->dndLeave( event.xclient.data.l ); else if( type == "XdndDrop" ) pDnd->dndDrop( event.xclient.data.l ); break; } } }
Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow, HINSTANCE hInst, HWND hParentWindow, bool dragDrop, bool playOnDrop, Win32Window *pParentWindow, GenericWindow::WindowType_t type ): OSWindow( pIntf ), m_dragDrop( dragDrop ), m_isLayered( false ), m_pParent( pParentWindow ), m_type ( type ) { (void)hParentWindow; Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( getIntf() ); const char* vlc_name = "VlC Media Player"; const char* vlc_class = "SkinWindowClass"; // Create the window if( type == GenericWindow::VoutWindow ) { // Child window (for vout) m_hWnd_parent = pParentWindow->getHandle(); m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW | WS_EX_NOPARENTNOTIFY, vlc_class, vlc_name, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 0, 0, m_hWnd_parent, 0, hInst, NULL ); } else if( type == GenericWindow::FullscreenWindow ) { // top-level window m_hWnd = CreateWindowEx( WS_EX_APPWINDOW, vlc_class, vlc_name, WS_POPUP | WS_CLIPCHILDREN, 0, 0, 0, 0, NULL, 0, hInst, NULL ); // Store with it a pointer to the interface thread SetWindowLongPtr( m_hWnd, GWLP_USERDATA, (LONG_PTR)getIntf() ); } else if( type == GenericWindow::FscWindow ) { VoutManager* pVoutManager = VoutManager::instance( getIntf() ); GenericWindow* pParent = (GenericWindow*)pVoutManager->getVoutMainWindow(); m_hWnd_parent = (HWND)pParent->getOSHandle(); // top-level window m_hWnd = CreateWindowEx( WS_EX_APPWINDOW, vlc_class, vlc_name, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 0, 0, m_hWnd_parent, 0, hInst, NULL ); // Store with it a pointer to the interface thread SetWindowLongPtr( m_hWnd, GWLP_USERDATA, (LONG_PTR)getIntf() ); } else { // top-level window (owned by the root window) HWND hWnd_owner = pFactory->getParentWindow(); m_hWnd = CreateWindowEx( 0, vlc_class, vlc_name, WS_POPUP | WS_CLIPCHILDREN, 0, 0, 0, 0, hWnd_owner, 0, hInst, NULL ); // Store with it a pointer to the interface thread SetWindowLongPtr( m_hWnd, GWLP_USERDATA, (LONG_PTR)getIntf() ); } if( !m_hWnd ) { msg_Err( getIntf(), "CreateWindow failed" ); return; } // Store a pointer to the GenericWindow in a map pFactory->m_windowMap[m_hWnd] = &rWindow; // Drag & drop if( m_dragDrop ) { m_pDropTarget = (LPDROPTARGET) new Win32DragDrop( getIntf(), playOnDrop, &rWindow ); // Register the window as a drop target RegisterDragDrop( m_hWnd, m_pDropTarget ); } }