634 lines
19 KiB
C
634 lines
19 KiB
C
/*
|
|
* Window related functions
|
|
*
|
|
* Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
|
|
* Copyright 1993 David Metcalfe
|
|
* Copyright 1995, 1996 Alex Korobka
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "ts_xlib.h"
|
|
#include "ts_xutil.h"
|
|
|
|
#include "winbase.h"
|
|
#include "wingdi.h"
|
|
#include "winuser.h"
|
|
|
|
#include "debugtools.h"
|
|
#include "x11drv.h"
|
|
#include "win.h"
|
|
#include "options.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(win);
|
|
|
|
extern Cursor X11DRV_MOUSE_XCursor; /* current X cursor */
|
|
extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
|
|
|
|
#define HAS_DLGFRAME(style,exStyle) \
|
|
((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
|
|
|
|
/* X context to associate a hwnd to an X window */
|
|
XContext winContext = 0;
|
|
|
|
Atom wmProtocols = None;
|
|
Atom wmDeleteWindow = None;
|
|
Atom dndProtocol = None;
|
|
Atom dndSelection = None;
|
|
Atom wmChangeState = None;
|
|
Atom kwmDockWindow = None;
|
|
Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
|
|
|
|
|
|
/***********************************************************************
|
|
* register_window
|
|
*
|
|
* Associate an X window to a HWND.
|
|
*/
|
|
static void register_window( HWND hwnd, Window win )
|
|
{
|
|
if (!winContext) winContext = TSXUniqueContext();
|
|
TSXSaveContext( display, win, winContext, (char *)hwnd );
|
|
TSXSetWMProtocols( display, win, &wmDeleteWindow, 1 );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* set_wm_hint
|
|
*
|
|
* Set a window manager hint.
|
|
*/
|
|
static void set_wm_hint( Window win, int hint, int val )
|
|
{
|
|
XWMHints* wm_hints = TSXGetWMHints( display, win );
|
|
if (!wm_hints) wm_hints = TSXAllocWMHints();
|
|
if (wm_hints)
|
|
{
|
|
wm_hints->flags = hint;
|
|
switch( hint )
|
|
{
|
|
case InputHint:
|
|
wm_hints->input = val;
|
|
break;
|
|
|
|
case StateHint:
|
|
wm_hints->initial_state = val;
|
|
break;
|
|
|
|
case IconPixmapHint:
|
|
wm_hints->icon_pixmap = (Pixmap)val;
|
|
break;
|
|
|
|
case IconWindowHint:
|
|
wm_hints->icon_window = (Window)val;
|
|
break;
|
|
}
|
|
TSXSetWMHints( display, win, wm_hints );
|
|
TSXFree(wm_hints);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* set_icon_hints
|
|
*
|
|
* Set the icon wm hints
|
|
*/
|
|
static void set_icon_hints( WND *wndPtr, XWMHints *hints )
|
|
{
|
|
X11DRV_WND_DATA *data = wndPtr->pDriverData;
|
|
HICON hIcon = GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
|
|
|
|
if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
|
|
if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
|
|
|
|
if (!hIcon)
|
|
{
|
|
data->hWMIconBitmap = 0;
|
|
data->hWMIconMask = 0;
|
|
hints->flags &= ~(IconPixmapHint | IconMaskHint);
|
|
}
|
|
else
|
|
{
|
|
HBITMAP hbmOrig;
|
|
RECT rcMask;
|
|
BITMAP bmMask;
|
|
ICONINFO ii;
|
|
HDC hDC;
|
|
|
|
GetIconInfo(hIcon, &ii);
|
|
|
|
X11DRV_CreateBitmap(ii.hbmMask);
|
|
X11DRV_CreateBitmap(ii.hbmColor);
|
|
|
|
GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
|
|
rcMask.top = 0;
|
|
rcMask.left = 0;
|
|
rcMask.right = bmMask.bmWidth;
|
|
rcMask.bottom = bmMask.bmHeight;
|
|
|
|
hDC = CreateCompatibleDC(0);
|
|
hbmOrig = SelectObject(hDC, ii.hbmMask);
|
|
InvertRect(hDC, &rcMask);
|
|
SelectObject(hDC, hbmOrig);
|
|
DeleteDC(hDC);
|
|
|
|
data->hWMIconBitmap = ii.hbmColor;
|
|
data->hWMIconMask = ii.hbmMask;
|
|
|
|
hints->icon_pixmap = X11DRV_BITMAP_Pixmap(data->hWMIconBitmap);
|
|
hints->icon_mask = X11DRV_BITMAP_Pixmap(data->hWMIconMask);
|
|
hints->flags |= IconPixmapHint | IconMaskHint;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* dock_window
|
|
*
|
|
* Set the X Property of the window that tells the windowmanager we really
|
|
* want to be in the systray
|
|
*
|
|
* KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
|
|
* mapped.
|
|
*
|
|
* all others: to be added ;)
|
|
*/
|
|
inline static void dock_window( Window win )
|
|
{
|
|
int data = 1;
|
|
if (kwmDockWindow != None)
|
|
TSXChangeProperty( display, win, kwmDockWindow, kwmDockWindow,
|
|
32, PropModeReplace, (char*)&data, 1 );
|
|
if (_kde_net_wm_system_tray_window_for != None)
|
|
TSXChangeProperty( display, win, _kde_net_wm_system_tray_window_for, XA_WINDOW,
|
|
32, PropModeReplace, (char*)&win, 1 );
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* create_desktop
|
|
*/
|
|
static void create_desktop(WND *wndPtr)
|
|
{
|
|
X11DRV_WND_DATA *data = wndPtr->pDriverData;
|
|
|
|
wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
|
|
wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
|
|
dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
|
|
dndSelection = TSXInternAtom( display, "DndSelection" , False );
|
|
wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
|
|
kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
|
|
_kde_net_wm_system_tray_window_for = TSXInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
|
|
|
|
data->window = root_window;
|
|
if (root_window != DefaultRootWindow(display)) wndPtr->flags |= WIN_NATIVE;
|
|
register_window( wndPtr->hwndSelf, root_window );
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* CreateWindow (X11DRV.@)
|
|
*/
|
|
BOOL X11DRV_CreateWindow( HWND hwnd )
|
|
{
|
|
X11DRV_WND_DATA *data;
|
|
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
|
int x = wndPtr->rectWindow.left;
|
|
int y = wndPtr->rectWindow.top;
|
|
int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
|
|
int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
|
|
|
|
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(X11DRV_WND_DATA))))
|
|
{
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return FALSE;
|
|
}
|
|
data->window = 0;
|
|
wndPtr->pDriverData = data;
|
|
|
|
if (!wndPtr->parent)
|
|
{
|
|
create_desktop( wndPtr );
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return TRUE;
|
|
}
|
|
|
|
/* Create the X window (only for top-level windows, and then only */
|
|
/* when there's no desktop window) */
|
|
|
|
if ((root_window == DefaultRootWindow(display))
|
|
&& (wndPtr->parent->hwndSelf == GetDesktopWindow()))
|
|
{
|
|
Window wGroupLeader;
|
|
XWMHints* wm_hints;
|
|
XSetWindowAttributes win_attr;
|
|
|
|
/* Create "managed" windows only if a title bar or resizable */
|
|
/* frame is required. */
|
|
if (WIN_WindowNeedsWMBorder(wndPtr->dwStyle, wndPtr->dwExStyle))
|
|
{
|
|
win_attr.event_mask = ExposureMask | KeyPressMask |
|
|
KeyReleaseMask | PointerMotionMask |
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
FocusChangeMask | StructureNotifyMask;
|
|
win_attr.override_redirect = FALSE;
|
|
wndPtr->dwExStyle |= WS_EX_MANAGED;
|
|
}
|
|
else
|
|
{
|
|
win_attr.event_mask = ExposureMask | KeyPressMask |
|
|
KeyReleaseMask | PointerMotionMask |
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
FocusChangeMask;
|
|
win_attr.override_redirect = TRUE;
|
|
}
|
|
wndPtr->flags |= WIN_NATIVE;
|
|
|
|
win_attr.bit_gravity = (wndPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ? ForgetGravity : NorthWestGravity;
|
|
win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
|
|
win_attr.backing_store = NotUseful;
|
|
win_attr.save_under = ((wndPtr->clsStyle & CS_SAVEBITS) != 0);
|
|
win_attr.cursor = X11DRV_MOUSE_XCursor;
|
|
|
|
data->hWMIconBitmap = 0;
|
|
data->hWMIconMask = 0;
|
|
data->bit_gravity = win_attr.bit_gravity;
|
|
|
|
/* Zero-size X11 window hack. X doesn't like them, and will crash */
|
|
/* with a BadValue unless we do something ugly like this. */
|
|
/* Zero size window won't be mapped */
|
|
if (cx <= 0) cx = 1;
|
|
if (cy <= 0) cy = 1;
|
|
|
|
data->window = TSXCreateWindow( display, root_window,
|
|
x, y, cx, cy,
|
|
0, screen_depth,
|
|
InputOutput, visual,
|
|
CWEventMask | CWOverrideRedirect |
|
|
CWColormap | CWCursor | CWSaveUnder |
|
|
CWBackingStore | CWBitGravity,
|
|
&win_attr );
|
|
|
|
if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, data );
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return FALSE;
|
|
}
|
|
|
|
/* If we are the systray, we need to be managed to be noticed by KWM */
|
|
if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW) dock_window( data->window );
|
|
|
|
if (wndPtr->dwExStyle & WS_EX_MANAGED)
|
|
{
|
|
XClassHint *class_hints = TSXAllocClassHint();
|
|
XSizeHints* size_hints = TSXAllocSizeHints();
|
|
|
|
if (class_hints)
|
|
{
|
|
class_hints->res_name = "wineManaged";
|
|
class_hints->res_class = "Wine";
|
|
TSXSetClassHint( display, data->window, class_hints );
|
|
TSXFree (class_hints);
|
|
}
|
|
|
|
if (size_hints)
|
|
{
|
|
size_hints->win_gravity = StaticGravity;
|
|
size_hints->x = x;
|
|
size_hints->y = y;
|
|
size_hints->flags = PWinGravity|PPosition;
|
|
|
|
if (HAS_DLGFRAME(wndPtr->dwStyle,wndPtr->dwExStyle))
|
|
{
|
|
size_hints->min_width = size_hints->max_width = cx;
|
|
size_hints->min_height = size_hints->max_height = cy;
|
|
size_hints->flags |= PMinSize | PMaxSize;
|
|
}
|
|
|
|
TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
|
|
size_hints, XA_WM_NORMAL_HINTS );
|
|
TSXFree(size_hints);
|
|
}
|
|
}
|
|
|
|
if (wndPtr->owner) /* Get window owner */
|
|
{
|
|
Window w = X11DRV_WND_FindXWindow( wndPtr->owner );
|
|
if (w != None)
|
|
{
|
|
TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
|
|
wGroupLeader = w;
|
|
}
|
|
}
|
|
|
|
if ((wm_hints = TSXAllocWMHints()))
|
|
{
|
|
wm_hints->flags = InputHint | StateHint | WindowGroupHint;
|
|
wm_hints->input = True;
|
|
|
|
if (wndPtr->dwExStyle & WS_EX_MANAGED)
|
|
{
|
|
set_icon_hints( wndPtr, wm_hints );
|
|
wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
|
|
? IconicState : NormalState;
|
|
}
|
|
else
|
|
wm_hints->initial_state = NormalState;
|
|
wm_hints->window_group = wGroupLeader;
|
|
|
|
TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
|
|
TSXFree(wm_hints);
|
|
}
|
|
register_window( hwnd, data->window );
|
|
}
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* DestroyWindow (X11DRV.@)
|
|
*/
|
|
BOOL X11DRV_DestroyWindow( HWND hwnd )
|
|
{
|
|
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
|
X11DRV_WND_DATA *data = wndPtr->pDriverData;
|
|
Window w;
|
|
|
|
if (data && (w = data->window))
|
|
{
|
|
XEvent xe;
|
|
TSXDeleteContext( display, w, winContext );
|
|
TSXDestroyWindow( display, w );
|
|
while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
|
|
|
|
data->window = None;
|
|
if( data->hWMIconBitmap )
|
|
{
|
|
DeleteObject( data->hWMIconBitmap );
|
|
data->hWMIconBitmap = 0;
|
|
}
|
|
if( data->hWMIconMask )
|
|
{
|
|
DeleteObject( data->hWMIconMask);
|
|
data->hWMIconMask= 0;
|
|
}
|
|
}
|
|
HeapFree( GetProcessHeap(), 0, data );
|
|
wndPtr->pDriverData = NULL;
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
* SetParent (X11DRV.@)
|
|
*/
|
|
HWND X11DRV_SetParent( HWND hwnd, HWND parent )
|
|
{
|
|
WND *wndPtr;
|
|
WND *pWndParent;
|
|
DWORD dwStyle;
|
|
HWND retvalue;
|
|
|
|
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
|
|
|
|
dwStyle = wndPtr->dwStyle;
|
|
|
|
pWndParent = parent ? WIN_FindWndPtr(parent) : WIN_GetDesktop();
|
|
if (!pWndParent)
|
|
{
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return 0;
|
|
}
|
|
|
|
/* Windows hides the window first, then shows it again
|
|
* including the WM_SHOWWINDOW messages and all */
|
|
if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
|
|
|
|
retvalue = wndPtr->parent->hwndSelf; /* old parent */
|
|
if (pWndParent != wndPtr->parent)
|
|
{
|
|
if ( X11DRV_WND_GetXWindow(wndPtr) )
|
|
{
|
|
/* Toplevel window needs to be reparented. Used by Tk 8.0 */
|
|
TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
|
|
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
|
|
}
|
|
WIN_UnlinkWindow(wndPtr->hwndSelf);
|
|
wndPtr->parent = pWndParent;
|
|
|
|
/* Create an X counterpart for reparented top-level windows
|
|
* when not in the desktop mode. */
|
|
if (parent == GetDesktopWindow())
|
|
{
|
|
if(root_window == DefaultRootWindow(display))
|
|
X11DRV_CreateWindow(wndPtr->hwndSelf);
|
|
}
|
|
else /* a child window */
|
|
{
|
|
if( !( wndPtr->dwStyle & WS_CHILD ) )
|
|
{
|
|
if( wndPtr->wIDmenu != 0)
|
|
{
|
|
DestroyMenu( (HMENU) wndPtr->wIDmenu );
|
|
wndPtr->wIDmenu = 0;
|
|
}
|
|
}
|
|
}
|
|
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
|
|
}
|
|
WIN_ReleaseWndPtr( pWndParent );
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
|
|
/* SetParent additionally needs to make hwnd the topmost window
|
|
in the x-order and send the expected WM_WINDOWPOSCHANGING and
|
|
WM_WINDOWPOSCHANGED notification messages.
|
|
*/
|
|
SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
|
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
|
|
((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
|
|
/* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
|
|
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
|
|
|
|
return retvalue;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* EnableWindow (X11DRV.@)
|
|
*/
|
|
BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
|
|
{
|
|
WND *wndPtr;
|
|
BOOL retvalue;
|
|
Window w;
|
|
|
|
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
|
|
|
|
retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
|
|
|
|
if (enable && (wndPtr->dwStyle & WS_DISABLED))
|
|
{
|
|
/* Enable window */
|
|
wndPtr->dwStyle &= ~WS_DISABLED;
|
|
|
|
if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
|
|
set_wm_hint( w, InputHint, TRUE );
|
|
|
|
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
|
|
}
|
|
else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
|
|
{
|
|
SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0 );
|
|
|
|
/* Disable window */
|
|
wndPtr->dwStyle |= WS_DISABLED;
|
|
|
|
if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
|
|
set_wm_hint( w, InputHint, FALSE );
|
|
|
|
if (hwnd == GetFocus())
|
|
SetFocus( 0 ); /* A disabled window can't have the focus */
|
|
|
|
if (hwnd == GetCapture())
|
|
ReleaseCapture(); /* A disabled window can't capture the mouse */
|
|
|
|
SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
|
|
}
|
|
WIN_ReleaseWndPtr(wndPtr);
|
|
return retvalue;
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
* SetFocus (X11DRV.@)
|
|
*
|
|
* Set the X focus.
|
|
* Explicit colormap management seems to work only with OLVWM.
|
|
*/
|
|
void X11DRV_SetFocus( HWND hwnd )
|
|
{
|
|
XWindowAttributes win_attr;
|
|
Window win;
|
|
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
|
WND *w = wndPtr;
|
|
|
|
if (!wndPtr) return;
|
|
|
|
/* Only mess with the X focus if there's */
|
|
/* no desktop window and if the window is not managed by the WM. */
|
|
if (root_window != DefaultRootWindow(display)) goto done;
|
|
|
|
while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
|
|
w = w->parent;
|
|
if (!w) w = wndPtr;
|
|
if (w->dwExStyle & WS_EX_MANAGED) goto done;
|
|
|
|
if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
|
|
{
|
|
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
|
|
TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
|
|
}
|
|
else if ((win = X11DRV_WND_FindXWindow(wndPtr)))
|
|
{
|
|
/* Set X focus and install colormap */
|
|
if (TSXGetWindowAttributes( display, win, &win_attr ) &&
|
|
(win_attr.map_state == IsViewable))
|
|
{
|
|
/* If window is not viewable, don't change anything */
|
|
TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
|
|
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
|
|
TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
|
|
X11DRV_Synchronize();
|
|
}
|
|
}
|
|
|
|
done:
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
* SetWindowText (X11DRV.@)
|
|
*/
|
|
BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
|
|
{
|
|
UINT count;
|
|
char *buffer;
|
|
static UINT text_cp = (UINT)-1;
|
|
Window win;
|
|
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
|
|
|
if (!wndPtr) return FALSE;
|
|
if ((win = X11DRV_WND_GetXWindow(wndPtr)))
|
|
{
|
|
if (text_cp == (UINT)-1)
|
|
{
|
|
text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
|
|
TRACE("text_cp = %u\n", text_cp);
|
|
}
|
|
|
|
/* allocate new buffer for window text */
|
|
count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
|
|
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
|
|
{
|
|
ERR("Not enough memory for window text\n");
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return FALSE;
|
|
}
|
|
WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
|
|
|
|
TSXStoreName( display, win, buffer );
|
|
TSXSetIconName( display, win, buffer );
|
|
HeapFree( GetProcessHeap(), 0, buffer );
|
|
}
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* X11DRV_SetWindowIcon
|
|
*
|
|
* hIcon or hIconSm has changed (or is being initialised for the
|
|
* first time). Complete the X11 driver-specific initialisation
|
|
* and set the window hints.
|
|
*
|
|
* This is not entirely correct, may need to create
|
|
* an icon window and set the pixmap as a background
|
|
*/
|
|
HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
|
|
{
|
|
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
|
int index = small ? GCL_HICONSM : GCL_HICON;
|
|
HICON old;
|
|
|
|
if (!wndPtr) return 0;
|
|
|
|
old = GetClassLongW( hwnd, index );
|
|
SetClassLongW( hwnd, index, icon );
|
|
|
|
SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
|
|
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
|
|
|
|
if (wndPtr->dwExStyle & WS_EX_MANAGED)
|
|
{
|
|
Window win = X11DRV_WND_GetXWindow(wndPtr);
|
|
XWMHints* wm_hints = TSXGetWMHints( display, win );
|
|
|
|
if (!wm_hints) wm_hints = TSXAllocWMHints();
|
|
if (wm_hints)
|
|
{
|
|
set_icon_hints( wndPtr, wm_hints );
|
|
TSXSetWMHints( display, win, wm_hints );
|
|
TSXFree( wm_hints );
|
|
}
|
|
}
|
|
|
|
WIN_ReleaseWndPtr( wndPtr );
|
|
return old;
|
|
}
|