hw/xwin: xcbify code for converting X11 icon to Win32 icon

Convert the code for converting an X11 icon to Win32 icon from Xlib to xcb.

v2: some warning fixes in winXIconToHICON()
v3: declaration-after-statement warning fixes
v4: printf format fixes
v5: convert in place rather than in a library

This also avoids the xlib/xserver namespace collision issues, so
winmultiwindowicons.h can be included everywhere it should be, which fixes
compilation with -Werror=implicit-function-declaration

Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
Jon Turney 2015-11-02 17:55:19 +00:00
parent 0a69c1e2fa
commit 6a64b9d7af
7 changed files with 94 additions and 61 deletions

View File

@ -2150,7 +2150,7 @@ if test "x$XWIN" = xyes; then
AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
AC_CHECK_TOOL(WINDRES, windres)
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes])
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes x11-xcb xcb-image xcb-icccm])
if test "x$WINDOWSWM" = xauto; then
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])

View File

@ -36,15 +36,21 @@
#define WINVER 0x0500
#endif
#include <limits.h>
#include <stdbool.h>
#include <X11/Xwindows.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <xcb/xcb.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_image.h>
#include "winresource.h"
#include "winprefs.h"
#include "winmsg.h"
#include "winmultiwindowicons.h"
#include "winglobals.h"
/*
* global variables
*/
@ -57,7 +63,7 @@ extern HINSTANCE g_hInstance;
static void
winScaleXImageToWindowsIcon(int iconSize,
int effBPP,
int stride, XImage * pixmap, unsigned char *image)
int stride, xcb_image_t* pixmap, unsigned char *image)
{
int row, column, effXBPP, effXDepth;
unsigned char *outPtr;
@ -69,15 +75,15 @@ winScaleXImageToWindowsIcon(int iconSize,
unsigned int zero;
unsigned int color;
effXBPP = pixmap->bits_per_pixel;
if (pixmap->bits_per_pixel == 15)
effXBPP = pixmap->bpp;
if (pixmap->bpp == 15)
effXBPP = 16;
effXDepth = pixmap->depth;
if (pixmap->depth == 15)
effXDepth = 16;
xStride = pixmap->bytes_per_line;
xStride = pixmap->stride;
if (stride == 0 || xStride == 0) {
ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. "
"Bailing.\n");
@ -330,8 +336,8 @@ NetWMToWinIconThreshold(uint32_t * icon)
static HICON
NetWMToWinIcon(int bpp, uint32_t * icon)
{
static Bool hasIconAlphaChannel = FALSE;
static BOOL versionChecked = FALSE;
static bool hasIconAlphaChannel = FALSE;
static bool versionChecked = FALSE;
if (!versionChecked) {
OSVERSIONINFOEX osvi = { 0 };
@ -366,8 +372,8 @@ NetWMToWinIcon(int bpp, uint32_t * icon)
*/
static
HICON
winXIconToHICON(Display * pDisplay, Window id, int iconSize)
HICON
winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize)
{
unsigned char *mask, *image = NULL, *imageMask;
unsigned char *dst, *src;
@ -375,16 +381,13 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
unsigned int biggest_size = 0;
HDC hDC;
ICONINFO ii;
XWMHints *hints;
xcb_icccm_wm_hints_t hints;
HICON hIcon = NULL;
uint32_t *biggest_icon = NULL;
static Atom _XA_NET_WM_ICON;
static xcb_atom_t _XA_NET_WM_ICON;
static int generation;
uint32_t *icon, *icon_data = NULL;
unsigned long int size;
Atom type;
int format;
unsigned long int left;
hDC = GetDC(GetDesktopWindow());
planes = GetDeviceCaps(hDC, PLANES);
@ -393,17 +396,31 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
/* Always prefer _NET_WM_ICON icons */
if (generation != serverGeneration) {
xcb_intern_atom_reply_t *atom_reply;
xcb_intern_atom_cookie_t atom_cookie;
const char *atomName = "_NET_WM_ICON";
generation = serverGeneration;
_XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE);
_XA_NET_WM_ICON = XCB_NONE;
atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
if (atom_reply) {
_XA_NET_WM_ICON = atom_reply->atom;
free(atom_reply);
}
}
if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON,
0, MAXINT, FALSE,
AnyPropertyType, &type, &format, &size, &left,
(unsigned char **) &icon_data) == Success) &&
(icon_data != NULL)) {
for (icon = icon_data; icon < &icon_data[size] && *icon;
icon = &icon[icon[0] * icon[1] + 2]) {
{
xcb_get_property_cookie_t cookie = xcb_get_property(conn, FALSE, id, _XA_NET_WM_ICON, XCB_ATOM_CARDINAL, 0L, INT_MAX);
xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL);
if (reply &&
((icon_data = xcb_get_property_value(reply)) != NULL)) {
size = xcb_get_property_value_length(reply)/sizeof(uint32_t);
for (icon = icon_data; icon < &icon_data[size] && *icon;
icon = &icon[icon[0] * icon[1] + 2]) {
winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
/* Icon data size will overflow an int and thus is bigger than the
@ -441,40 +458,46 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
hIcon = NetWMToWinIcon(bpp, biggest_icon);
}
XFree(icon_data);
free(reply);
}
}
if (!hIcon) {
xcb_get_property_cookie_t wm_hints_cookie;
winDebug("winXIconToHICON: no suitable NetIcon\n");
hints = XGetWMHints(pDisplay, id);
if (hints) {
wm_hints_cookie = xcb_icccm_get_wm_hints(conn, id);
if (xcb_icccm_get_wm_hints_reply(conn, wm_hints_cookie, &hints, NULL)) {
winDebug("winXIconToHICON: id 0x%x icon_pixmap hint 0x%x\n",
(unsigned int)id,
(unsigned int)hints->icon_pixmap);
(unsigned int)hints.icon_pixmap);
if (hints->icon_pixmap) {
Window root;
int x, y;
unsigned int width, height, border_width, depth;
XImage *xImageIcon;
XImage *xImageMask = NULL;
if (hints.icon_pixmap) {
unsigned int width, height;
xcb_image_t *xImageIcon;
xcb_image_t *xImageMask = NULL;
XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y,
&width, &height, &border_width, &depth);
xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, hints.icon_pixmap);
xcb_get_geometry_reply_t *geom_reply = xcb_get_geometry_reply(conn, geom_cookie, NULL);
xImageIcon =
XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height,
0xFFFFFFFF, ZPixmap);
winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%p\n",
(unsigned int)id, xImageIcon);
if (geom_reply) {
width = geom_reply->width;
height = geom_reply->height;
if (hints->icon_mask)
xImageMask =
XGetImage(pDisplay, hints->icon_mask, 0, 0, width,
height, 0xFFFFFFFF, ZPixmap);
xImageIcon = xcb_image_get(conn, hints.icon_pixmap,
0, 0, width, height,
0xFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
if (xImageIcon) {
winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%p\n",
(unsigned int)id, xImageIcon);
if (hints.icon_mask)
xImageMask = xcb_image_get(conn, hints.icon_mask,
0, 0, width, height,
0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
if (xImageIcon) {
int effBPP, stride, maskStride;
/* 15 BPP is really 16BPP as far as we care */
@ -543,12 +566,12 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
free(imageMask);
if (xImageMask)
XDestroyImage(xImageMask);
xcb_image_destroy(xImageMask);
XDestroyImage(xImageIcon);
xcb_image_destroy(xImageIcon);
}
}
}
XFree(hints);
}
}
return hIcon;
@ -560,20 +583,22 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
#ifdef XWIN_MULTIWINDOW
void
winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew)
winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew)
{
HICON hIcon, hIconSmall = NULL, hIconOld;
/* Start with the icon from preferences, if any */
hIcon = hIconNew;
hIconSmall = hIconNew;
/* If we still need an icon, try and get the icon from WM_HINTS */
if (!hIcon)
hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON));
if (!hIconSmall)
hIconSmall =
winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON));
if (hIconNew)
{
/* Start with the icon from preferences, if any */
hIcon = hIconNew;
hIconSmall = hIconNew;
}
else
{
/* If we still need an icon, try and get the icon from WM_HINTS */
hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON));
hIconSmall = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXSMICON));
}
/* If we got the small, but not the large one swap them */
if (!hIcon && hIconSmall) {

View File

@ -27,8 +27,10 @@
#ifndef WINMULTIWINDOWICONS_H
#define WINMULTIWINDOWICONS_H
#include <xcb/xcb.h>
void
winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew);
winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew);
void
winInitGlobalIcons(void);

View File

@ -35,9 +35,11 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"
#include "dixevents.h"
#include "winmultiwindowclass.h"
#include "winmultiwindowicons.h"
/*
* Prototypes for local functions

View File

@ -48,6 +48,7 @@
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlocale.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
@ -62,6 +63,7 @@
#include "windowstr.h"
#include "winglobals.h"
#include "windisplay.h"
#include "winmultiwindowicons.h"
#ifdef XWIN_MULTIWINDOWEXTWM
#include <X11/extensions/windowswmstr.h>
@ -628,7 +630,7 @@ UpdateIcon(WMInfoPtr pWMInfo, Window iWindow)
}
}
winUpdateIcon(hWnd, pWMInfo->pDisplay, iWindow, hIconNew);
winUpdateIcon(hWnd, XGetXCBConnection(pWMInfo->pDisplay), iWindow, hIconNew);
}
/*

View File

@ -46,6 +46,7 @@
#include "winprefs.h"
#include "windisplay.h"
#include "winmultiwindowclass.h"
#include "winmultiwindowicons.h"
/* Where will the custom menu commands start counting from? */
#define STARTMENUID WM_USER

View File

@ -40,6 +40,7 @@
#define _WINDOWSWM_SERVER_
#include <X11/extensions/windowswmstr.h>
#include "winmultiwindowclass.h"
#include "winmultiwindowicons.h"
#include <X11/Xatom.h>
/*