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_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
AC_CHECK_TOOL(WINDRES, windres) 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 if test "x$WINDOWSWM" = xauto; then
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])

View File

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

View File

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

View File

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

View File

@ -48,6 +48,7 @@
#include <X11/X.h> #include <X11/X.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlocale.h> #include <X11/Xlocale.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
@ -62,6 +63,7 @@
#include "windowstr.h" #include "windowstr.h"
#include "winglobals.h" #include "winglobals.h"
#include "windisplay.h" #include "windisplay.h"
#include "winmultiwindowicons.h"
#ifdef XWIN_MULTIWINDOWEXTWM #ifdef XWIN_MULTIWINDOWEXTWM
#include <X11/extensions/windowswmstr.h> #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 "winprefs.h"
#include "windisplay.h" #include "windisplay.h"
#include "winmultiwindowclass.h" #include "winmultiwindowclass.h"
#include "winmultiwindowicons.h"
/* Where will the custom menu commands start counting from? */ /* Where will the custom menu commands start counting from? */
#define STARTMENUID WM_USER #define STARTMENUID WM_USER

View File

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