winex11.drv: Preliminary support for Xinerama.

This commit is contained in:
Alexandre Julliard 2006-10-23 14:37:17 +02:00
parent 7d00b0504e
commit 3c305f9db9
8 changed files with 178 additions and 8 deletions

View File

@ -39,6 +39,7 @@ C_SRCS = \
xdnd.c \
xfont.c \
xim.c \
xinerama.c \
xrandr.c \
xrender.c \
xvidmode.c

View File

@ -1154,7 +1154,7 @@ static BOOL BITBLT_GetVisRectangles( X11DRV_PDEVICE *physDevDst, INT xDst, INT y
GetObjectW( physDevSrc->bitmap->hbitmap, sizeof(bm), &bm );
SetRect( &clipRect, 0, 0, bm.bmWidth, bm.bmHeight );
}
else SetRect( &clipRect, 0, 0, screen_width, screen_height );
else clipRect = virtual_screen_rect;
if (!IntersectRect( visRectSrc, &rect, &clipRect ))
return FALSE;

View File

@ -141,6 +141,7 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height )
max_height = screen_height;
screen_width = width;
screen_height = height;
xinerama_init();
/* initialize the available resolutions */
dd_modes = X11DRV_Settings_SetHandlers("desktop",

View File

@ -110,8 +110,11 @@ BOOL X11DRV_is_window_rect_mapped( const RECT *rect )
if (IsRectEmpty( rect )) return FALSE;
/* don't map if rect is off-screen */
if (rect->left >= (int)screen_width || rect->top >= (int)screen_height) return FALSE;
if (rect->right < 0 || rect->bottom < 0) return FALSE;
if (rect->left >= virtual_screen_rect.right ||
rect->top >= virtual_screen_rect.bottom ||
rect->right <= virtual_screen_rect.left ||
rect->bottom <= virtual_screen_rect.top)
return FALSE;
return TRUE;
}
@ -335,7 +338,7 @@ static void systray_dock_window( Display *display, struct x11drv_win_data *data
* For more information on this problem, see
* http://standards.freedesktop.org/xembed-spec/latest/ar01s04.html */
SetWindowPos( data->hwnd, NULL, screen_width + 1, screen_height + 1,
SetWindowPos( data->hwnd, NULL, virtual_screen_rect.right + 1, virtual_screen_rect.bottom + 1,
0, 0, SWP_NOZORDER | SWP_NOSIZE );
/* set XEMBED protocol data on the window */
@ -938,7 +941,6 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd )
/* fill in the desktop X window id in the x11drv_win_data structure */
static void get_desktop_xwin( Display *display, struct x11drv_win_data *data )
{
RECT rect;
Window win = (Window)GetPropA( data->hwnd, whole_window_prop );
if (win)
@ -967,8 +969,8 @@ static void get_desktop_xwin( Display *display, struct x11drv_win_data *data )
SetPropA( data->hwnd, whole_window_prop, (HANDLE)root_window );
SetPropA( data->hwnd, visual_id_prop, (HANDLE)visualid );
data->whole_window = root_window;
SetRect( &rect, 0, 0, screen_width, screen_height );
X11DRV_set_window_pos( data->hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL );
X11DRV_set_window_pos( data->hwnd, 0, &virtual_screen_rect, &virtual_screen_rect,
SWP_NOZORDER, NULL );
if (root_window != DefaultRootWindow( display ))
{
data->managed = TRUE;

View File

@ -1253,6 +1253,7 @@ void X11DRV_handle_desktop_resize( unsigned int width, unsigned int height )
screen_width = width;
screen_height = height;
xinerama_init();
TRACE("desktop %p change to (%dx%d)\n", hwnd, width, height);
SetRect( &rect, 0, 0, width, height );
data->lock_changes++;
@ -1665,7 +1666,7 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
else
{
parent = 0;
SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
mouseRect = virtual_screen_rect;
}
origRect = sizingRect;

View File

@ -526,12 +526,14 @@ extern Window root_window;
extern unsigned int screen_width;
extern unsigned int screen_height;
extern unsigned int screen_depth;
extern RECT virtual_screen_rect;
extern unsigned int text_caps;
extern int use_xkb;
extern int use_take_focus;
extern int use_primary_selection;
extern int managed_mode;
extern int private_color_map;
extern int primary_monitor;
extern int copy_default_colors;
extern int alloc_system_colors;
extern int xrender_error_base;
@ -686,6 +688,7 @@ extern void X11DRV_sync_window_position( Display *display, struct x11drv_win_dat
extern BOOL X11DRV_set_window_pos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
const RECT *rectClient, UINT swp_flags, const RECT *validRects );
extern void X11DRV_set_wm_hints( Display *display, struct x11drv_win_data *data );
extern void xinerama_init(void);
extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height );
extern void X11DRV_handle_desktop_resize(unsigned int width, unsigned int height);

View File

@ -69,6 +69,7 @@ Visual *visual;
unsigned int screen_width;
unsigned int screen_height;
unsigned int screen_depth;
RECT virtual_screen_rect;
Window root_window;
int dxgrab = 0;
int usexvidmode = 1;
@ -78,6 +79,7 @@ int use_take_focus = 1;
int use_primary_selection = 0;
int managed_mode = 1;
int private_color_map = 0;
int primary_monitor = 0;
int client_side_with_core = 1;
int client_side_with_render = 1;
int client_side_antialias_with_core = 1;
@ -358,6 +360,9 @@ static void setup_options(void)
if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
private_color_map = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
primary_monitor = atoi( buffer );
if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
copy_default_colors = atoi(buffer);
@ -429,6 +434,7 @@ static BOOL process_attach(void)
screen_width = WidthOfScreen( screen );
screen_height = HeightOfScreen( screen );
xinerama_init();
X11DRV_Settings_Init();
#ifdef HAVE_LIBXXF86VM

156
dlls/winex11.drv/xinerama.c Normal file
View File

@ -0,0 +1,156 @@
/*
* Xinerama support
*
* Copyright 2006 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#ifdef HAVE_X11_EXTENSIONS_XINERAMA_H
#include <X11/extensions/Xinerama.h>
#endif
#include "wine/library.h"
#include "x11drv.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
static MONITORINFOEXW default_monitor =
{
sizeof(default_monitor), /* cbSize */
{ 0, 0, 0, 0 }, /* rcMonitor */
{ 0, 0, 0, 0 }, /* rcWork */
MONITORINFOF_PRIMARY, /* dwFlags */
{ '\\','\\','.','\\','D','I','S','P','L','A','Y','1',0 } /* szDevice */
};
static MONITORINFOEXW *monitors;
static int nb_monitors;
static inline MONITORINFOEXW *get_primary(void)
{
/* default to 0 if specified primary is invalid */
int idx = primary_monitor;
if (idx >= nb_monitors) idx = 0;
return &monitors[idx];
}
#ifdef HAVE_LIBXINERAMA
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(XineramaQueryExtension);
MAKE_FUNCPTR(XineramaQueryScreens);
static void load_xinerama(void)
{
void *handle;
if (!(handle = wine_dlopen(SONAME_LIBXINERAMA, RTLD_NOW, NULL, 0)))
{
WARN( "failed to open %s\n", SONAME_LIBXINERAMA );
return;
}
pXineramaQueryExtension = wine_dlsym( handle, "XineramaQueryExtension", NULL, 0 );
if (!pXineramaQueryExtension) WARN( "XineramaQueryScreens not found\n" );
pXineramaQueryScreens = wine_dlsym( handle, "XineramaQueryScreens", NULL, 0 );
if (!pXineramaQueryScreens) WARN( "XineramaQueryScreens not found\n" );
}
static int query_screens(void)
{
int i, count, event_base, error_base;
XineramaScreenInfo *screens;
if (!monitors) /* first time around */
load_xinerama();
if (!pXineramaQueryExtension || !pXineramaQueryScreens ||
!pXineramaQueryExtension( gdi_display, &event_base, &error_base ) ||
!(screens = pXineramaQueryScreens( gdi_display, &count ))) return 0;
if (monitors != &default_monitor) HeapFree( GetProcessHeap(), 0, monitors );
if ((monitors = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*monitors) )))
{
nb_monitors = count;
for (i = 0; i < nb_monitors; i++)
{
/* FIXME: for now, force primary to be the screen that starts at (0,0) origin */
if (!screens[i].x_org && !screens[i].y_org) primary_monitor = i;
monitors[i].cbSize = sizeof( monitors[i] );
monitors[i].rcMonitor.left = screens[i].x_org;
monitors[i].rcMonitor.top = screens[i].y_org;
monitors[i].rcMonitor.right = screens[i].x_org + screens[i].width;
monitors[i].rcMonitor.bottom = screens[i].y_org + screens[i].height;
monitors[i].rcWork = monitors[i].rcMonitor;
monitors[i].dwFlags = 0;
/* FIXME: using the same device name for all monitors for now */
lstrcpyW( monitors[i].szDevice, default_monitor.szDevice );
}
get_primary()->dwFlags |= MONITORINFOF_PRIMARY;
for (i = 0; i < nb_monitors; i++)
TRACE( "monitor %d: %s%s\n",
i, wine_dbgstr_rect(&monitors[i].rcMonitor),
(monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" );
}
else count = 0;
XFree( screens );
return count;
}
#else /* HAVE_LIBXINERAMA */
static inline int query_screens(void)
{
return 0;
}
#endif /* HAVE_LIBXINERAMA */
void xinerama_init(void)
{
MONITORINFOEXW *primary;
wine_tsx11_lock();
SetRect( &virtual_screen_rect, 0, 0, screen_width, screen_height );
if (root_window != DefaultRootWindow( gdi_display ) || !query_screens())
{
default_monitor.rcWork = default_monitor.rcMonitor = virtual_screen_rect;
nb_monitors = 1;
monitors = &default_monitor;
}
primary = get_primary();
/* coordinates (0,0) have to point to the primary monitor origin */
OffsetRect( &virtual_screen_rect, -primary->rcMonitor.left, -primary->rcMonitor.top );
screen_width = primary->rcMonitor.right - primary->rcMonitor.left;
screen_height = primary->rcMonitor.bottom - primary->rcMonitor.top;
TRACE( "virtual size: %s primary size: %dx%d\n",
wine_dbgstr_rect(&virtual_screen_rect), screen_width, screen_height );
wine_tsx11_unlock();
}