From a19b6aaeb2516e8af2e3ae6b97e19f3df2219efd Mon Sep 17 00:00:00 2001 From: Alex Pasadyn Date: Tue, 16 Sep 2003 20:24:29 +0000 Subject: [PATCH] - Allow applications to resize the Wine desktop window. - Some cleanup of ChangeDisplaySettings and friends. --- dlls/x11drv/desktop.c | 214 +++++++++++++++++++++++++++++++++++++++++ dlls/x11drv/x11ddraw.c | 5 +- dlls/x11drv/x11drv.h | 5 + dlls/x11drv/xvidmode.c | 190 +++++++++++++++++++++++++++--------- 4 files changed, 368 insertions(+), 46 deletions(-) diff --git a/dlls/x11drv/desktop.c b/dlls/x11drv/desktop.c index 494d95eb23d..171d66321ad 100644 --- a/dlls/x11drv/desktop.c +++ b/dlls/x11drv/desktop.c @@ -25,7 +25,9 @@ #include "wine/winuser16.h" #include "win.h" +#include "ddrawi.h" #include "x11drv.h" +#include "x11ddraw.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(x11drv); @@ -111,6 +113,93 @@ void X11DRV_create_desktop_thread(void) } +/* data for resolution changing */ +static LPDDHALMODEINFO dd_modes; +static int nmodes; + +static unsigned int max_width; +static unsigned int max_height; + +static const unsigned int widths[] = {320, 640, 800, 1024, 1280, 1600}; +static const unsigned int heights[] = {200, 480, 600, 768, 1024, 1200}; + +/* fill in DD mode info for one mode*/ +static void make_one_mode (LPDDHALMODEINFO info, unsigned int width, unsigned int height) +{ + info->dwWidth = width; + info->dwHeight = height; + info->wRefreshRate = 0; + info->lPitch = 0; + info->dwBPP = 0; + info->wFlags = 0; + info->dwRBitMask = 0; + info->dwGBitMask = 0; + info->dwBBitMask = 0; + info->dwAlphaBitMask = 0; + TRACE("initialized mode %dx%d\n", width, height); +} + +/* create the mode structures */ +static void make_modes(void) +{ + int i; + nmodes = 2; + for (i=0; i<6; i++) + { + if ( (widths[i] <= max_width) && (heights[i] <= max_height) ) nmodes++; + } + dd_modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDHALMODEINFO) * nmodes); + /* mode 0 is the original specified desktop size */ + make_one_mode(&dd_modes[0], screen_width, screen_height); + /* mode 1 is the root window size */ + make_one_mode(&dd_modes[1], max_width, max_height); + /* these modes are all the standard modes smaller than the root window */ + for (i=2; imin_width = size_hints->max_width = width; + size_hints->min_height = size_hints->max_height = height; + size_hints->flags = PMinSize | PMaxSize | PSize; + + /* do the work */ + XSetWMNormalHints( display, w, size_hints ); + XResizeWindow( display, w, width, height ); + screen_width = width; + screen_height = height; +#if 0 /* FIXME */ + SYSMETRICS_Set( SM_CXSCREEN, width ); + SYSMETRICS_Set( SM_CYSCREEN, height ); +#endif + + /* clean up */ + XFree( size_hints ); + XFlush( display ); + wine_tsx11_unlock(); + return 1; +} + + /*********************************************************************** * X11DRV_create_desktop * @@ -131,6 +220,8 @@ Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry ) wine_tsx11_lock(); flags = XParseGeometry( geometry, &x, &y, &width, &height ); + max_width = screen_width; + max_height = screen_height; screen_width = width; screen_height = height; @@ -180,5 +271,128 @@ Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry ) XFree( class_hints ); XFlush( display ); wine_tsx11_unlock(); + /* initialize the available resolutions */ + make_modes(); return win; } + +void X11DRV_desktop_SetCurrentMode(int mode) +{ + if (mode < nmodes) + { + X11DRV_resize_desktop(dd_modes[mode].dwWidth, dd_modes[mode].dwHeight); + } +} + +int X11DRV_desktop_GetCurrentMode(void) +{ + int i; + for (i=0; idmDisplayFlags = 0; + devmode->dmDisplayFrequency = 85; + devmode->dmSize = sizeof(DEVMODEW); + if (n==0 || n == (DWORD)-1 || n == (DWORD)-2) + { + devmode->dmBitsPerPel = dwBpp; + devmode->dmPelsHeight = dd_modes[0].dwHeight; + devmode->dmPelsWidth = dd_modes[0].dwWidth; + devmode->dmFields = (DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL); + TRACE("mode %ld -- returning default %ldx%ldx%ldbpp\n", n, + devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel); + return TRUE; + } + if (n <= nmodes) + { + devmode->dmPelsWidth = dd_modes[n].dwWidth; + devmode->dmPelsHeight = dd_modes[n].dwHeight; + devmode->dmBitsPerPel = dwBpp; + devmode->dmFields = (DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL); + TRACE("mode %ld -- %ldx%ldx%ldbpp\n", n, + devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel); + return TRUE; + } + TRACE("mode %ld -- not present\n", n); + return FALSE; +} + +/* implementation of ChangeDisplaySettings for desktop */ +LONG X11DRV_desktop_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, + HWND hwnd, DWORD flags, LPVOID lpvoid ) +{ + DWORD i; + DWORD dwBpp = screen_depth; + if (dwBpp == 24) dwBpp = 32; + if (devmode==NULL) + { + X11DRV_desktop_SetCurrentMode(0); + return DISP_CHANGE_SUCCESSFUL; + } + + for (i = 0; i < nmodes; i++) + { + if (devmode->dmFields & DM_BITSPERPEL) + { + if (devmode->dmBitsPerPel != dwBpp) + continue; + } + if (devmode->dmFields & DM_PELSWIDTH) + { + if (devmode->dmPelsWidth != dd_modes[i].dwWidth) + continue; + } + if (devmode->dmFields & DM_PELSHEIGHT) + { + if (devmode->dmPelsHeight != dd_modes[i].dwHeight) + continue; + } + /* we have a valid mode */ + TRACE("Matches mode %ld\n", i); + X11DRV_desktop_SetCurrentMode(i); +#if 0 /* FIXME */ + SYSMETRICS_Set( SM_CXSCREEN, devmode->dmPelsWidth ); + SYSMETRICS_Set( SM_CYSCREEN, devmode->dmPelsHeight ); +#endif + return DISP_CHANGE_SUCCESSFUL; + } + + /* no valid modes found */ + ERR("No matching mode found!\n"); + return DISP_CHANGE_BADMODE; +} + +/* DirectDraw HAL stuff */ + +static DWORD PASCAL X11DRV_desktop_SetMode(LPDDHAL_SETMODEDATA data) +{ + X11DRV_desktop_SetCurrentMode(data->dwModeIndex); + X11DRV_DDHAL_SwitchMode(data->dwModeIndex, NULL, NULL); + data->ddRVal = DD_OK; + return DDHAL_DRIVER_HANDLED; +} + +int X11DRV_desktop_CreateDriver(LPDDHALINFO info) +{ + if (!nmodes) return 0; /* no desktop */ + + info->dwNumModes = nmodes; + info->lpModeInfo = dd_modes; + X11DRV_DDHAL_SwitchMode(X11DRV_desktop_GetCurrentMode(), NULL, NULL); + info->lpDDCallbacks->SetMode = X11DRV_desktop_SetMode; + return TRUE; +} diff --git a/dlls/x11drv/x11ddraw.c b/dlls/x11drv/x11ddraw.c index 7f563cbdb28..15981dd6a5d 100644 --- a/dlls/x11drv/x11ddraw.c +++ b/dlls/x11drv/x11ddraw.c @@ -383,8 +383,11 @@ INT X11DRV_DCICommand(INT cbInput, const DCICMD *lpCmd, LPVOID lpOutData) #endif { #ifdef HAVE_LIBXXF86VM - X11DRV_XF86VM_CreateDriver(&hal_info); + if (!X11DRV_XF86VM_CreateDriver(&hal_info)) #endif + { + X11DRV_desktop_CreateDriver(&hal_info); + } } #ifdef HAVE_OPENGL /*X11DRV_GLX_CreateDriver(&hal_info);*/ diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h index ab11d8bd303..f9354823431 100644 --- a/dlls/x11drv/x11drv.h +++ b/dlls/x11drv/x11drv.h @@ -43,6 +43,7 @@ typedef int Status; #include "gdi.h" #include "user.h" #include "win.h" +#include "ddrawi.h" #include "thread.h" #define MAX_PIXELFORMATS 8 @@ -490,6 +491,10 @@ extern void X11DRV_window_to_X_rect( WND *win, RECT *rect ); extern void X11DRV_X_to_window_rect( WND *win, RECT *rect ); extern void X11DRV_create_desktop_thread(void); extern Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry ); +extern int X11DRV_desktop_CreateDriver(LPDDHALINFO info); +extern BOOL X11DRV_desktop_EnumDisplaySettingsExW( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags); +extern LONG X11DRV_desktop_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, + HWND hwnd, DWORD flags, LPVOID lpvoid ); extern void X11DRV_sync_window_style( Display *display, WND *win ); extern int X11DRV_sync_whole_window_position( Display *display, WND *win, int zorder ); extern int X11DRV_sync_client_window_position( Display *display, WND *win ); diff --git a/dlls/x11drv/xvidmode.c b/dlls/x11drv/xvidmode.c index 35988ffcf0a..a81c17edbac 100644 --- a/dlls/x11drv/xvidmode.c +++ b/dlls/x11drv/xvidmode.c @@ -104,11 +104,13 @@ static int XVidModeErrorHandler(Display *dpy, XErrorEvent *event, void *arg) return 1; } +static Bool in_desktop_mode; + void X11DRV_XF86VM_Init(void) { int nmodes, i; Bool ok; - Bool in_desktop_mode = (root_window != DefaultRootWindow(gdi_display)); + in_desktop_mode = (root_window != DefaultRootWindow(gdi_display)); if (xf86vm_major) return; /* already initialized? */ @@ -417,10 +419,8 @@ BOOL X11DRV_SetDeviceGammaRamp(X11DRV_PDEVICE *physDev, LPVOID ramp) #endif } -/*********************************************************************** - * EnumDisplaySettingsExW (X11DRV.@) - */ -BOOL X11DRV_EnumDisplaySettingsExW( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags) +/* implementation of EnumDisplaySettings for XF86VM */ +BOOL X11DRV_XF86VM_EnumDisplaySettingsExW( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags) { DWORD dwBpp = screen_depth; if (dwBpp == 24) dwBpp = 32; @@ -456,59 +456,22 @@ BOOL X11DRV_EnumDisplaySettingsExW( LPCWSTR name, DWORD n, LPDEVMODEW devmode, D return FALSE; } - - -#define _X_FIELD(prefix, bits) if ((fields) & prefix##_##bits) {p+=sprintf(p, "%s%s", first ? "" : ",", #bits); first=FALSE;} -static const char * _CDS_flags(DWORD fields) -{ - BOOL first = TRUE; - char buf[128]; - char *p = buf; - _X_FIELD(CDS,UPDATEREGISTRY);_X_FIELD(CDS,TEST);_X_FIELD(CDS,FULLSCREEN); - _X_FIELD(CDS,GLOBAL);_X_FIELD(CDS,SET_PRIMARY);_X_FIELD(CDS,RESET); - _X_FIELD(CDS,SETRECT);_X_FIELD(CDS,NORESET); - *p = 0; - return wine_dbg_sprintf("%s", buf); -} -static const char * _DM_fields(DWORD fields) -{ - BOOL first = TRUE; - char buf[128]; - char *p = buf; - _X_FIELD(DM,BITSPERPEL);_X_FIELD(DM,PELSWIDTH);_X_FIELD(DM,PELSHEIGHT); - _X_FIELD(DM,DISPLAYFLAGS);_X_FIELD(DM,DISPLAYFREQUENCY);_X_FIELD(DM,POSITION); - *p = 0; - return wine_dbg_sprintf("%s", buf); -} -#undef _X_FIELD - -/*********************************************************************** - * ChangeDisplaySettingsExW (X11DRV.@) - */ -LONG X11DRV_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, +/* implementation of ChangeDisplaySettings for desktop */ +LONG X11DRV_XF86VM_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lpvoid ) { DWORD i; DWORD dwBpp = screen_depth; if (dwBpp == 24) dwBpp = 32; - TRACE("(%s,%p,%p,0x%08lx,%p\n",debugstr_w(devname),devmode,hwnd,flags,lpvoid); - TRACE("flags=%s\n",_CDS_flags(flags)); if (devmode==NULL) { - TRACE("Return to original display mode\n"); #ifdef HAVE_LIBXXF86VM X11DRV_XF86VM_SetCurrentMode(xf86vm_initial_mode); #endif return DISP_CHANGE_SUCCESSFUL; } - if (TRACE_ON(x11drv)) - { - TRACE("DM_fields=%s\n",_DM_fields(devmode->dmFields)); - TRACE("width=%ld height=%ld bpp=%ld freq=%ld\n", - devmode->dmPelsWidth,devmode->dmPelsHeight, - devmode->dmBitsPerPel,devmode->dmDisplayFrequency); - } +#if 0 /* FIXME: only works if we update SYSMETRICS */ if ((!(devmode->dmFields & DM_BITSPERPEL) || devmode->dmBitsPerPel == dwBpp) && (!(devmode->dmFields & DM_PELSWIDTH) || devmode->dmPelsWidth == GetSystemMetrics(SM_CXSCREEN)) && (!(devmode->dmFields & DM_PELSHEIGHT) || devmode->dmPelsHeight == GetSystemMetrics(SM_CYSCREEN))) @@ -517,6 +480,7 @@ LONG X11DRV_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, TRACE("Requested mode matches current mode -- no change!\n"); return DISP_CHANGE_SUCCESSFUL; } +#endif #ifdef HAVE_LIBXXF86VM for (i = 0; i < xf86vm_mode_count; i++) @@ -552,3 +516,139 @@ LONG X11DRV_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, ERR("No matching mode found!\n"); return DISP_CHANGE_BADMODE; } + +/* implementation of EnumDisplaySettings for nores */ +BOOL X11DRV_nores_EnumDisplaySettingsExW( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags) +{ + DWORD dwBpp = screen_depth; + if (dwBpp == 24) dwBpp = 32; + devmode->dmDisplayFlags = 0; + devmode->dmDisplayFrequency = 85; + devmode->dmSize = sizeof(DEVMODEW); + if (n==0 || n == (DWORD)-1 || n == (DWORD)-2) + { + devmode->dmBitsPerPel = dwBpp; + devmode->dmPelsHeight = GetSystemMetrics(SM_CYSCREEN); + devmode->dmPelsWidth = GetSystemMetrics(SM_CXSCREEN); + devmode->dmFields = (DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL); + TRACE("mode %ld -- returning default %ldx%ldx%ldbpp\n", n, + devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel); + return TRUE; + } + TRACE("mode %ld -- not present\n", n); + return FALSE; +} + +/* implementation of ChangeDisplaySettings for nores */ +LONG X11DRV_nores_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, + HWND hwnd, DWORD flags, LPVOID lpvoid ) +{ + DWORD dwBpp = screen_depth; + if (dwBpp == 24) dwBpp = 32; + if (devmode==NULL) + { + return DISP_CHANGE_SUCCESSFUL; + } + + if ((!(devmode->dmFields & DM_BITSPERPEL) || devmode->dmBitsPerPel == dwBpp) && + (!(devmode->dmFields & DM_PELSWIDTH) || devmode->dmPelsWidth == GetSystemMetrics(SM_CXSCREEN)) && + (!(devmode->dmFields & DM_PELSHEIGHT) || devmode->dmPelsHeight == GetSystemMetrics(SM_CYSCREEN))) + { + /* we are in the desired mode */ + TRACE("Requested mode matches current mode -- no change!\n"); + return DISP_CHANGE_SUCCESSFUL; + } + + /* no valid modes found */ + ERR("No matching mode found!\n"); + return DISP_CHANGE_BADMODE; +} + +/*********************************************************************** + * EnumDisplaySettingsExW (X11DRV.@) + * + * FIXME: should move to somewhere appropriate + */ +BOOL X11DRV_EnumDisplaySettingsExW( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags) +{ + if (xf86vm_modes) + { + /* XVidMode */ + return X11DRV_XF86VM_EnumDisplaySettingsExW(name, n, devmode, flags); + } + else if (in_desktop_mode) + { + /* desktop */ + return X11DRV_desktop_EnumDisplaySettingsExW(name, n, devmode, flags); + } + else + { + /* no resolution changing */ + return X11DRV_nores_EnumDisplaySettingsExW(name, n, devmode, flags); + } +} + +#define _X_FIELD(prefix, bits) if ((fields) & prefix##_##bits) {p+=sprintf(p, "%s%s", first ? "" : ",", #bits); first=FALSE;} +static const char * _CDS_flags(DWORD fields) +{ + BOOL first = TRUE; + char buf[128]; + char *p = buf; + _X_FIELD(CDS,UPDATEREGISTRY);_X_FIELD(CDS,TEST);_X_FIELD(CDS,FULLSCREEN); + _X_FIELD(CDS,GLOBAL);_X_FIELD(CDS,SET_PRIMARY);_X_FIELD(CDS,RESET); + _X_FIELD(CDS,SETRECT);_X_FIELD(CDS,NORESET); + *p = 0; + return wine_dbg_sprintf("%s", buf); +} +static const char * _DM_fields(DWORD fields) +{ + BOOL first = TRUE; + char buf[128]; + char *p = buf; + _X_FIELD(DM,BITSPERPEL);_X_FIELD(DM,PELSWIDTH);_X_FIELD(DM,PELSHEIGHT); + _X_FIELD(DM,DISPLAYFLAGS);_X_FIELD(DM,DISPLAYFREQUENCY);_X_FIELD(DM,POSITION); + *p = 0; + return wine_dbg_sprintf("%s", buf); +} +#undef _X_FIELD + +/*********************************************************************** + * ChangeDisplaySettingsExW (X11DRV.@) + * + * FIXME: should move to somewhere appropriate + */ +LONG X11DRV_ChangeDisplaySettingsExW( LPCWSTR devname, LPDEVMODEW devmode, + HWND hwnd, DWORD flags, LPVOID lpvoid ) +{ + TRACE("(%s,%p,%p,0x%08lx,%p\n",debugstr_w(devname),devmode,hwnd,flags,lpvoid); + TRACE("flags=%s\n",_CDS_flags(flags)); + if (devmode) + { + TRACE("DM_fields=%s\n",_DM_fields(devmode->dmFields)); + TRACE("width=%ld height=%ld bpp=%ld freq=%ld\n", + devmode->dmPelsWidth,devmode->dmPelsHeight, + devmode->dmBitsPerPel,devmode->dmDisplayFrequency); + } + else + { + TRACE("Return to original display mode\n"); + } + if (xf86vm_modes) + { + /* XVidMode */ + return X11DRV_XF86VM_ChangeDisplaySettingsExW( devname, devmode, + hwnd, flags, lpvoid ); + } + else if (in_desktop_mode) + { + /* no XVidMode */ + return X11DRV_desktop_ChangeDisplaySettingsExW( devname, devmode, + hwnd, flags, lpvoid ); + } + else + { + /* no resolution changing */ + return X11DRV_nores_ChangeDisplaySettingsExW( devname, devmode, + hwnd, flags, lpvoid ); + } +}