From 6a64b9d7af70dc7ff2cac8b35a1f7b0797823733 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 2 Nov 2015 17:55:19 +0000 Subject: 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 Reviewed-by: Colin Harrison --- configure.ac | 2 +- hw/xwin/winmultiwindowicons.c | 151 ++++++++++++++++++++++++----------------- hw/xwin/winmultiwindowicons.h | 4 +- hw/xwin/winmultiwindowwindow.c | 2 + hw/xwin/winmultiwindowwm.c | 4 +- hw/xwin/winprefs.c | 1 + hw/xwin/winwin32rootless.c | 1 + 7 files changed, 99 insertions(+), 66 deletions(-) diff --git a/configure.ac b/configure.ac index dff06efdc..1e78b7dfd 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c index cc4538709..050795123 100644 --- a/hw/xwin/winmultiwindowicons.c +++ b/hw/xwin/winmultiwindowicons.c @@ -36,15 +36,21 @@ #define WINVER 0x0500 #endif +#include +#include + #include #include -#include +#include +#include +#include #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); - - if (hints->icon_pixmap) { - Window root; - int x, y; - unsigned int width, height, border_width, depth; - XImage *xImageIcon; - XImage *xImageMask = NULL; - - XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y, - &width, &height, &border_width, &depth); - - 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 (hints->icon_mask) - xImageMask = - XGetImage(pDisplay, hints->icon_mask, 0, 0, width, - height, 0xFFFFFFFF, ZPixmap); - - if (xImageIcon) { + (unsigned int)hints.icon_pixmap); + + if (hints.icon_pixmap) { + unsigned int width, height; + xcb_image_t *xImageIcon; + xcb_image_t *xImageMask = NULL; + + 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); + + 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); + + 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) { diff --git a/hw/xwin/winmultiwindowicons.h b/hw/xwin/winmultiwindowicons.h index bf7f6eda7..87ba8d1cf 100644 --- a/hw/xwin/winmultiwindowicons.h +++ b/hw/xwin/winmultiwindowicons.h @@ -27,8 +27,10 @@ #ifndef WINMULTIWINDOWICONS_H #define WINMULTIWINDOWICONS_H +#include + void - winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew); + winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew); void winInitGlobalIcons(void); diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 6db576a92..e82d91591 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -35,9 +35,11 @@ #ifdef HAVE_XWIN_CONFIG_H #include #endif + #include "win.h" #include "dixevents.h" #include "winmultiwindowclass.h" +#include "winmultiwindowicons.h" /* * Prototypes for local functions diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index c5404cfe3..e594794c1 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ #include "windowstr.h" #include "winglobals.h" #include "windisplay.h" +#include "winmultiwindowicons.h" #ifdef XWIN_MULTIWINDOWEXTWM #include @@ -628,7 +630,7 @@ UpdateIcon(WMInfoPtr pWMInfo, Window iWindow) } } - winUpdateIcon(hWnd, pWMInfo->pDisplay, iWindow, hIconNew); + winUpdateIcon(hWnd, XGetXCBConnection(pWMInfo->pDisplay), iWindow, hIconNew); } /* diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c index 505292714..a180a9e8f 100644 --- a/hw/xwin/winprefs.c +++ b/hw/xwin/winprefs.c @@ -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 diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c index 95b845230..52806887f 100644 --- a/hw/xwin/winwin32rootless.c +++ b/hw/xwin/winwin32rootless.c @@ -40,6 +40,7 @@ #define _WINDOWSWM_SERVER_ #include #include "winmultiwindowclass.h" +#include "winmultiwindowicons.h" #include /* -- cgit v1.2.3