diff options
author | Mihai Moldovan <ionic@ionic.de> | 2017-07-14 01:25:20 +0200 |
---|---|---|
committer | Mihai Moldovan <ionic@ionic.de> | 2017-07-14 01:25:20 +0200 |
commit | 5796ac64427755b255db91c9b902e387e0ea68fc (patch) | |
tree | adf3a76db11fc7d20c6c800e47ecd6d10acfef4b /nxcompshad/src/Win.cpp | |
parent | 622360ea2ec9cde354aece445e4b9fb4b7664eea (diff) | |
parent | 59e829f3647005a6c93662adfbcea36e27a993d8 (diff) | |
download | nx-libs-5796ac64427755b255db91c9b902e387e0ea68fc.tar.gz nx-libs-5796ac64427755b255db91c9b902e387e0ea68fc.tar.bz2 nx-libs-5796ac64427755b255db91c9b902e387e0ea68fc.zip |
Merge branch 'sunweaver-pr/nxcompshad-autoreconf' into 3.6.x
Attributes GH PR #474: https://github.com/ArcticaProject/nx-libs/pull/474
Diffstat (limited to 'nxcompshad/src/Win.cpp')
-rw-r--r-- | nxcompshad/src/Win.cpp | 1149 |
1 files changed, 1149 insertions, 0 deletions
diff --git a/nxcompshad/src/Win.cpp b/nxcompshad/src/Win.cpp new file mode 100644 index 000000000..6033f2c1b --- /dev/null +++ b/nxcompshad/src/Win.cpp @@ -0,0 +1,1149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */ +/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */ +/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */ +/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(__CYGWIN32__) || defined(WIN32) + +#include <nx-X11/keysym.h> + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include "Poller.h" +#include "Logger.h" + +Poller::Poller(Input *input, Display *display, int depth) : CorePoller(input, display) +{ + logTrace("Poller::Poller"); + + screenDC_ = NULL; + screenBmp_ = NULL; + memoryDC_ = NULL; + pDIBbits_ = NULL; + DIBBuffer_ = NULL; + pKey_ = NULL; + pMouse_ = NULL; + path_ = NULL; + keymapName_ = input -> getKeymap(); + keymap_ = NULL; + toggleButtonState_ = 0; + serverModifierState_ = 0; + display_ = display; + depth_ = DefaultDepth(display_, DefaultScreen(display_)); + oldCursor_ = 0; + xCursor_ = 0; +} + +Poller::~Poller() +{ + logTrace("Poller::~Poller"); + + if (screenDC_) + { + BOOL result = ReleaseDC(NULL, screenDC_); + + logTest("Poller::~Poller", "ReleaseDC returned [%d].", result); + + screenDC_ = NULL; + } + + if (memoryDC_) + { + BOOL result = DeleteDC(memoryDC_); + + logTest("Poller::~Poller", "DeleteDC returned [%d].", result); + + memoryDC_ = NULL; + } + + if (screenBmp_) + { + BOOL result = DeleteObject(screenBmp_); + + logTest("Poller::~Poller", "DeleteObject returned [%d].", result); + + screenBmp_ = NULL; + } + + if (DIBBuffer_) + { + logDebug("Poller::~Poller", "Delete DIBBuffer_ [%p].", DIBBuffer_); + + delete [] DIBBuffer_; + } + + if (pKey_) + { + logDebug("Poller::~Poller", " pKey_[%p].", pKey_); + + delete [] pKey_; + } + + if (pMouse_) + { + logDebug("Poller::~Poller", " pMouse_[%p].", pMouse_); + + delete [] pMouse_; + } + + if (keymap_) + { + logDebug("Poller::~Poller", " keymap_[%p].", keymap_); + + delete [] keymap_; + } +} + +int Poller::init() +{ + logTrace("Poller::init"); + + int maxLengthArrayINPUT = 6; + + platformOS(); + + pKey_ = new INPUT [maxLengthArrayINPUT]; + + if (pKey_ == NULL) + { + logError("Poller::init", ESET(ENOMEM)); + + return -1; + } + + for (int i = 0; i < maxLengthArrayINPUT; i++) + { + pKey_[i].type = INPUT_KEYBOARD; + pKey_[i].ki.wVk = (WORD) 0; + pKey_[i].ki.time = (DWORD) 0; + pKey_[i].ki.dwExtraInfo = (DWORD) 0; + } + + pMouse_ = new INPUT; + + if (pMouse_ == NULL) + { + logError("Poller::init", ESET(ENOMEM)); + + return -1; + } + + pMouse_ -> type = INPUT_MOUSE; + + pMouse_ -> mi.dx = 0; + pMouse_ -> mi.dy = 0; + pMouse_ -> mi.mouseData = (DWORD) 0; + pMouse_ -> mi.time = 0; + pMouse_ -> mi.dwExtraInfo = (ULONG_PTR) NULL; + + screenDC_ = GetDC(NULL); + + if (screenDC_ == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + switch(depth_) + { + case 8: + { + depth_ = 16; + break; + } + case 16: + { + depth_ = 16; + break; + } + case 24: + { + depth_ = 32; + break; + } + default: + { + logError("Poller::init", ESET(EINVAL)); + + return -1; + } + } + + width_ = GetDeviceCaps(screenDC_, HORZRES); + height_ = GetDeviceCaps(screenDC_, VERTRES); + + bpl_ = width_ * (depth_ >> 3); + bpp_ = (depth_ >> 3); + + logTest("Poller::init", "Screen geometry is [%d, %d] depth is [%d] bpl [%d] bpp [%d].", + width_, height_, depth_, bpl_, bpp_); + + logTest("Poller::init", "Got device context at [%p] screen size is (%d,%d).", + screenDC_, width_, height_); + + memoryDC_ = CreateCompatibleDC(screenDC_); + + if (memoryDC_ == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + // + // Delete the old bitmap for the memory device. + // + + HBITMAP bitmap = (HBITMAP) GetCurrentObject(memoryDC_, OBJ_BITMAP); + + if (bitmap && DeleteObject(bitmap) == 0) + { + logError("Poller::init", ESET(ENOMSG)); + } + + // + // Bitmap header describing the bitmap we want to get from GetDIBits. + // + + bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi_.bmiHeader.biWidth = width_; + bmi_.bmiHeader.biHeight = -height_; + bmi_.bmiHeader.biPlanes = 1; + bmi_.bmiHeader.biBitCount = depth_; + bmi_.bmiHeader.biCompression = BI_RGB; + bmi_.bmiHeader.biSizeImage = 0; + bmi_.bmiHeader.biXPelsPerMeter = 0; + bmi_.bmiHeader.biYPelsPerMeter = 0; + bmi_.bmiHeader.biClrUsed = 0; + bmi_.bmiHeader.biClrImportant = 0; + + screenBmp_ = CreateDIBSection(memoryDC_, &bmi_, DIB_RGB_COLORS, &pDIBbits_, NULL, 0); + ReleaseDC(NULL,memoryDC_); + + if (screenBmp_ == NULL) + { + logTest ("Poller::init", "This video device is not supporting DIB section"); + + pDIBbits_ = NULL; + + screenBmp_ = CreateCompatibleBitmap(screenDC_, width_, height_); + + if (screenBmp_ == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + if (SelectObject(memoryDC_, screenBmp_) == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + } + else + { + logTest ("Poller::init", "Enabled the DIB section"); + + if (SelectObject(memoryDC_, screenBmp_) == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + } + + // + // Check if the screen device raster capabilities + // support the bitmap transfer. + // + + if ((GetDeviceCaps(screenDC_, RASTERCAPS) & RC_BITBLT) == 0) + { + logTest("Poller::init", "This video device is not supporting the bitmap transfer."); + + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + // + // Check if the memory device raster capabilities + // support the GetDIBits and SetDIBits functions. + // + + if ((GetDeviceCaps(memoryDC_, RASTERCAPS) & RC_DI_BITMAP) == 0) + { + logTest("Poller::init", "This memory device is not supporting the GetDIBits and SetDIBits " + "function."); + + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + if (GetDeviceCaps(screenDC_, PLANES) != 1) + { + logTest("Poller::init", "This video device has more than 1 color plane."); + + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + return CorePoller::init(); +} + +// +// FIXME: Remove me. +// + +void ErrorExit(LPTSTR lpszFunction) +{ + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + logTest(lpszFunction, " Failed with error [%ld]: %s", dw, (char*)lpMsgBuf); + + LocalFree(lpMsgBuf); + ExitProcess(dw); +} + +// +// FIXME: End. +// + +char *Poller::getRect(XRectangle r) +{ + logTrace("Poller::getRect"); + + logDebug("Poller::getRect", "Going to retrive rectangle [%d, %d, %d, %d].", + r.x, r.y, r.width, r.height); + + // + // The CAPTUREBLT operation could be a very + // cpu-consuming task. We should make some + // test to see how much it is expensive. + // Anyway we get tooltip windows and any + // other special effect not included with + // only the SRCCOPY operation. + // + + if (BitBlt(memoryDC_, r.x, r.y, r.width, r.height, + screenDC_, r.x, r.y, SRCCOPY | CAPTUREBLT) == 0) + { + logError("Poller::getRect", ESET(ENOMSG)); + + logTest("Poller::getRect", "Failed to perform a bit-block transfer."); + logTest("Poller::getRect", "bit-block error=%lu", GetLastError()); + + return NULL; + } + + // bmi_.bmiHeader.biWidth = r.width; + // bmi_.bmiHeader.biHeight = -r.height; + + if (pDIBbits_ == NULL) + { + static long nPixel = 0; + + if (nPixel < r.width * r.height) + { + + if (DIBBuffer_) + { + delete [] DIBBuffer_; + } + + nPixel = r.width * r.height; + + DIBBuffer_ = new char [nPixel * bpp_]; + + if (DIBBuffer_ == NULL) + { + logError("Poller::getRect", ESET(ENOMEM)); + + nPixel = 0; + + return NULL; + } + } + + if (GetDIBits(memoryDC_, screenBmp_, height_ - r.height - r.y, r.height, + DIBBuffer_, &bmi_, DIB_RGB_COLORS) == 0) + { + logError("Poller::getRect", ESET(ENOMSG)); + + logTest("Poller::getRect", "Failed to retrieve the screen bitmap."); + + return NULL; + } + + return DIBBuffer_; + } + else + { + return (char *) pDIBbits_ + r.y * bpl_ + r.x * bpp_; + } +} + +void Poller::handleKeyboardEvent(Display *display, XEvent *event) +{ + KeySym keysym; + char *keyname = new char [31]; + keyTranslation tr = {0, 0}; + unsigned char scancode = 0; + int lengthArrayINPUT = 0; + + if (XLookupString((XKeyEvent *) event, keyname, 30, &keysym, NULL) > 0) + { + logTest("Poller::handleKeyboardEvent", "keyname %s, keysym [%x]", keyname, (unsigned int)keysym); + } + + if (specialKeys(keysym, event -> xkey.state, event -> type) == 1) + { + delete[] keyname; + return; + } + + tr = xkeymapTranslateKey(keysym, event -> xkey.keycode, event -> xkey.state); + scancode = tr.scancode; + + logTest("Poller::handleKeyboardEvent", "keyname [%s] scancode [0x%x], keycode[0x%x], keysym [%x]", keyname, + tr.scancode, event ->xkey.keycode, (unsigned int)keysym); + + if (scancode == 0) + { + delete[] keyname; + return; + } + + if (event -> type == KeyPress) + { + int test1 = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + int test2 = MapVirtualKey(0x24, MAPVK_VSC_TO_VK_EX); + + if (test1 == test2) + { + simulateCtrlAltDel(); + } + + if (isModifier(scancode) == 0) + { + savedServerModifierState_ = serverModifierState_; + } + + ensureServerModifiers(tr, &lengthArrayINPUT); + if (sendInput(scancode, 1, &lengthArrayINPUT) == 0) + { + logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT); + } + restoreServerModifiers(scancode); + } + else if (event -> type == KeyRelease) + { + if (sendInput(scancode, 0, &lengthArrayINPUT) == 0) + { + logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT); + } + } + + updateModifierState(scancode, (event -> type == KeyPress)); + + delete[] keyname; +} + +void Poller::handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) +{ +/* +FIXME +*/ +} + +void Poller::handleMouseEvent(Display *display, XEvent *event) +{ + DWORD flg = 0; + DWORD whl = 0; + + if (event -> type == ButtonPress) + { + logTest("Poller::handleMouseEvent", "ButtonPress.\n"); + switch (event -> xbutton.button) + { + case Button1: + { + flg = MOUSEEVENTF_LEFTDOWN; + break; + } + case Button2: + { + flg = MOUSEEVENTF_MIDDLEDOWN; + break; + } + case Button3: + { + flg = MOUSEEVENTF_RIGHTDOWN; + break; + } + case Button4: + { + flg = MOUSEEVENTF_WHEEL; + whl = WHEEL_DELTA; + pMouse_ -> mi.mouseData = whl; + break; + } + case Button5: + { + flg = MOUSEEVENTF_WHEEL; + whl = (DWORD) (-WHEEL_DELTA); + pMouse_ -> mi.mouseData = whl; + break; + } + } + } + else if (event -> type == ButtonRelease) + { + switch (event -> xbutton.button) + { + case Button1: + { + flg = MOUSEEVENTF_LEFTUP; + break; + } + case Button2: + { + flg = MOUSEEVENTF_MIDDLEUP; + break; + } + case Button3: + { + flg = MOUSEEVENTF_RIGHTUP; + break; + } + case Button4: + { + flg = MOUSEEVENTF_WHEEL; + whl = 0; + pMouse_ -> mi.mouseData = whl; + break; + } + case Button5: + { + flg = MOUSEEVENTF_WHEEL; + whl = 0; + pMouse_ -> mi.mouseData = whl; + break; + } + } + } + else if (event -> type == MotionNotify) + { + logTest("Poller::handleMouseEvent", "SetCursor - MotionNotify"); + + SetCursorPos(event -> xmotion.x, event -> xmotion.y); + } + + if (flg > 0) + { + // logTest("Poller::handleMouseEvent", "SetCursor - flg > 0"); + // + // FIXME: move the cursor to the pace the event occurred + // + + SetCursorPos(event -> xbutton.x, event -> xbutton.y); + + // + // FIXME: Remove me: send the click/release event + // mouse_event(flg, 0, 0, whl, (ULONG_PTR)NULL); + // + + pMouse_ -> mi.dwFlags = flg; + + if (SendInput(1, pMouse_, sizeof(INPUT)) == 0) + { + logTest("Poller::handleMouseEvent", "Failed SendInput"); + } + } +} + +int Poller::updateCursor(Window wnd, Visual* vis) +{ + BYTE *mBits, *andBits, *xorBits; + + logTrace("Poller::Cursor"); + + // + // Retrieve mouse cursor handle. + // + + CURSORINFO cursorInfo; + cursorInfo.cbSize = sizeof(CURSORINFO); + + if (GetCursorInfo(&cursorInfo) == 0) + { + logTest("Poller::Cursor", "GetCursorInfo() failed [%u].\n", (unsigned int)GetLastError()); + LocalFree(&cursorInfo); + return -1; + } + + HCURSOR hCursor = cursorInfo.hCursor; + + if (hCursor == 0) + { + logTest("Poller::Cursor","Cursor Handle is NULL. Error[%u].\n", (unsigned int)GetLastError()); + return 1; + } + + if (hCursor == oldCursor_) + { + LocalFree(&cursorInfo); + return 1; + } + else + { + oldCursor_ = hCursor; + } + + // + // Get cursor info. + // + + // logTest("Poller::Cursor","hCursor [%xH] GetCursor [%xH].\n", hCursor, GetCursor()); + + ICONINFO iconInfo; + if (GetIconInfo(hCursor, &iconInfo) == 0) + { + logTest("Poller::Cursor","GetIconInfo() failed. Error[%d].", (unsigned int)GetLastError()); + LocalFree(&iconInfo); + // return -1; + } + + BOOL isColorCursor = FALSE; + if (iconInfo.hbmColor != NULL) + { + isColorCursor = TRUE; + } + + if (iconInfo.hbmMask == NULL) + { + logTest("Poller::Cursor","Cursor bitmap handle is NULL.\n"); + return -1; + } + + // + // Check bitmap info for the cursor + // + + BITMAP bmMask; + if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), (LPVOID)&bmMask)) + { + logTest("Poller::Cursor","GetObject() for bitmap failed.\n"); + DeleteObject(iconInfo.hbmMask); + LocalFree(&bmMask); + return -1; + } + + if (bmMask.bmPlanes != 1 || bmMask.bmBitsPixel != 1) + { + logTest("Poller::Cursor","Incorrect data in cursor bitmap.\n"); + LocalFree(&bmMask); + DeleteObject(iconInfo.hbmMask); + return -1; + } + + // Get monochrome bitmap data for cursor + // NOTE: they say we should use GetDIBits() instead of GetBitmapBits(). + mBits = new BYTE[bmMask.bmWidthBytes * bmMask.bmHeight]; + + if (mBits == NULL)//Data bitmap + { + DeleteObject(iconInfo.hbmMask); + DestroyCursor(cursorInfo.hCursor); + LocalFree(&iconInfo); + LocalFree(&bmMask); + delete[] mBits; + return -1; + } + + BOOL success = GetBitmapBits(iconInfo.hbmMask, bmMask.bmWidthBytes * bmMask.bmHeight, mBits); + + if (!success) + { + logTest("Poller::Cursor","GetBitmapBits() failed.\n"); + delete[] mBits; + return -1; + } + + andBits = mBits; + + long width = bmMask.bmWidth; + long height = (isColorCursor) ? bmMask.bmHeight : bmMask.bmHeight/2; + + // + // The bitmask is formatted so that the upper half is + // the icon AND bitmask and the lower half is the icon XOR bitmask. + // + + if (!isColorCursor) + { + xorBits = andBits + bmMask.bmWidthBytes * height; + +/* logTest("Poller::Cursor","no color widthB[%ld] width[%ld] height[%ld] totByte[%ld] mbits[%ld].\n", + bmMask.bmWidthBytes,width,height,success,bmMask.bmHeight * bmMask.bmWidthBytes);*/ + + if (xCursor_ > 0) + { + XFreeCursor(display_, xCursor_); + } + + xCursor_ = createCursor(wnd, vis, (unsigned int)iconInfo.xHotspot, (unsigned int)iconInfo.yHotspot, + width, height, (unsigned char *)xorBits, (unsigned char *)andBits); + + XDefineCursor(display_, wnd, xCursor_); + } + + delete []mBits; + DeleteObject(iconInfo.hbmMask); + LocalFree(&bmMask); + DestroyCursor(cursorInfo.hCursor); + LocalFree(&iconInfo); + + return success; +} + +unsigned char Poller::specialKeys(unsigned int keysym, unsigned int state, int pressed) +{ + return 0; +} + +void Poller::ensureServerModifiers(keyTranslation tr, int *lengthArrayINPUT) +{ + return; +} + +void Poller::restoreServerModifiers(UINT scancode) +{ + keyTranslation dummy; + int lengthArrayINPUT = 0; + + if (isModifier(scancode) == 1) + { + return; + } + + dummy.scancode = 0; + dummy.modifiers = savedServerModifierState_; + ensureServerModifiers(dummy, &lengthArrayINPUT); + if (sendInput(0, 0, &lengthArrayINPUT) == 0) + { + logTest("Poller::restoreServerModifiers", "lengthArrayINPUT [%d]", lengthArrayINPUT); + } +} + +int Poller::updateShadowFrameBuffer(void) +{ + return 1; +} + +void Poller::addToKeymap(char *keyname, unsigned char scancode, unsigned short modifiers, char *mapname) +{ + return; +} + +FILE *Poller::xkeymapOpen(char *filename) +{ + return NULL; +} + +int Poller::xkeymapRead(char *mapname) +{ + return 1; +} + +void Poller::xkeymapInit(char *keyMapName) +{ + return; +} + +keyTranslation Poller::xkeymapTranslateKey(unsigned int keysym, unsigned int keycode, + unsigned int state) +{ + keyTranslation tr = { 0, 0 }; + + return tr; +} + +unsigned char Poller::getKeyState(unsigned int state, unsigned int keysym) +{ + return 0; +} + +char *Poller::getKsname(unsigned int keysym) +{ + char *ksname = NULL; + + return ksname; +} + +// +// Routine used to fool Winlogon into thinking CtrlAltDel was pressed +// +char Poller::simulateCtrlAltDel(void) +{ + HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId()); + + // + // Switch into the Winlogon desktop. + // + if (selectDesktopByName("Winlogon") == 0) + { + logTest("SimulateCtrlAltDelThreadFn","Failed to select logon desktop."); + return 0; + } + + logTest("SimulateCtrlAltDelThreadFn","Generating ctrl-alt-del."); + + // + // Winlogon uses hotkeys to trap Ctrl-Alt-Del. + // + PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE)); + + // + // Switch back to our original desktop. + // + if (oldDesktop != NULL) + { + selectDesktop(oldDesktop); + } + + return 1; +} + +// Switches the current thread into a different desktop by desktop handle +// This call takes care of all the evil memory management involved +char Poller::selectDesktop(HDESK newDesktop) +{ + // + // Only on NT. + // + if (isWinNT()) + { + HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId()); + + DWORD dummy; + char newName[256]; + + if (GetUserObjectInformation(newDesktop, UOI_NAME, &newName, 256, &dummy) == 0) + { + logDebug("Poller::selectDesktop","GetUserObjectInformation() failed. Error[%lu].", GetLastError()); + return 0; + } + + logTest("Poller::selectDesktop","New Desktop to [%s] (%x) from (%x).", + newName, (unsigned int)newDesktop, (unsigned int)oldDesktop); + + // + // Switch the desktop. + // + if(SetThreadDesktop(newDesktop) == 0) + { + logDebug("Poller::SelectDesktop","Unable to SetThreadDesktop(), Error=%lu.", GetLastError()); + return 0; + } + + // + // Switched successfully - destroy the old desktop. + // + if (CloseDesktop(oldDesktop) == 0) + { + logDebug("Poller::selectHdesk","Failed to close old desktop (%x), Error=%lu.", + (unsigned int)oldDesktop, GetLastError()); + return 0; + } + } + + return 1; +} + +// +// Switches the current thread into a different desktop, by name +// Calling with a valid desktop name will place the thread in that desktop. +// Calling with a NULL name will place the thread in the current input desktop. +// + +char Poller::selectDesktopByName(char *name) +{ + // + // Only on NT. + // + if (isWinNT()) + { + HDESK desktop; + + if (name != NULL) + { + // + // Attempt to open the named desktop. + // + desktop = OpenDesktop(name, 0, FALSE, + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + } + else + { + // + // Open the input desktop. + // + desktop = OpenInputDesktop(0, FALSE, + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + } + + if (desktop == NULL) + { + logDebug("Poller::selectDesktopByName","Unable to open desktop, Error=%lu.", GetLastError()); + return 0; + } + + // + // Switch to the new desktop + // + if (selectDesktop(desktop) == 0) + { + // + // Failed to enter the new desktop, so free it! + // + logDebug("Poller::selectDesktopByName","Failed to select desktop."); + + if (CloseDesktop(desktop) == 0) + { + logDebug("Poller::selectDesktopByName","Failed to close desktop, Error=%lu.", GetLastError()); + return 0; + } + } + + return 1; + } + + return (name == NULL); +} + +void Poller::platformOS() +{ + OSVERSIONINFO osversioninfo; + osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo); + + // + // Get the current OS version. + // + if (GetVersionEx(&osversioninfo) == 0) + { + platformID_ = 0; + } + platformID_ = osversioninfo.dwPlatformId; + +// +// versionMajor = osversioninfo.dwMajorVersion; +// versionMinor = osversioninfo.dwMinorVersion; +// +} + +char Poller::checkDesktop() +{ + // + // Only on NT. + // + if (isWinNT()) + { + // + // Get the input and thread desktops. + // + HDESK desktop = GetThreadDesktop(GetCurrentThreadId()); + HDESK inputDesktop = OpenInputDesktop(0, FALSE, + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + + if (inputDesktop == NULL) + { + return 0; + } + + DWORD dummy; + char desktopName[256]; + char inputName[256]; + + if (GetUserObjectInformation(desktop, UOI_NAME, &desktopName, 256, &dummy) == 0) + { + if (CloseDesktop(inputDesktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + } + + if (GetUserObjectInformation(inputDesktop, UOI_NAME, &inputName, 256, &dummy) == 0) + { + if (CloseDesktop(inputDesktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + } + + if (strcmp(desktopName, inputName) != 0) + { + // + // Switch to new desktop. + // + selectDesktop(inputDesktop); + } + + if (CloseDesktop(desktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + + if (CloseDesktop(inputDesktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + } + + return 1; +} + +unsigned char Poller::isModifier(UINT scancode) +{ + return 0; +} + +void Poller::updateModifierState(UINT scancode, unsigned char pressed) +{ + return; +} + +Cursor Poller::createCursor(Window wnd, Visual *vis,unsigned int x, unsigned int y, + int width, int height, unsigned char *xormask, unsigned char *andmask) +{ + Pixmap maskglyph, cursorglyph; + XColor bg, fg; + Cursor xcursor; + unsigned char *cursor; + unsigned char *mask, *pmask, *pcursor, tmp; + int scanline, offset; + + scanline = (width + 7) / 8; + offset = scanline * height; + + pmask = andmask; + pcursor = xormask; + for (int i = 0; i < offset; i++) + { + // + // The pixel is black if both the bit of andmask and xormask is one. + // + + tmp = *pcursor & *pmask; + *pcursor ^= tmp; + *pmask ^= tmp; + + *pmask = ~(*pmask); + + pmask++; + pcursor++; + } + + cursor = new unsigned char[offset]; + memcpy(cursor, xormask, offset); + + mask = new unsigned char[offset]; + memcpy(mask, andmask, offset); + + fg.red = fg.blue = fg.green = 0xffff; + bg.red = bg.blue = bg.green = 0x0000; + fg.flags = bg.flags = DoRed | DoBlue | DoGreen; + + cursorglyph = createGlyph(wnd, vis, width, height, cursor); + maskglyph = createGlyph(wnd, vis, width, height, mask); + + xcursor = XCreatePixmapCursor(display_, cursorglyph, maskglyph, &fg, &bg, x, y); + + XFreePixmap(display_, maskglyph); + XFreePixmap(display_, cursorglyph); + delete[]mask; + delete[]cursor; + + return xcursor; +} + +Pixmap Poller::createGlyph(Window wnd, Visual *visual, int width, int height, unsigned char *data) +{ + XImage *image; + Pixmap bitmap; + int scanline; + GC glyphGC; + + scanline = (width + 7) / 8; + + bitmap = XCreatePixmap(display_, wnd, width, height, 1); + glyphGC = XCreateGC(display_, bitmap, 0, NULL); + + image = XCreateImage(display_, visual, 1, ZPixmap, 0, (char *)data, width, height, 8, scanline); + image->byte_order = 1; // MSBFirst -- LSBFirst = 0 + image->bitmap_bit_order = 1; + XInitImage(image); + +/* logTest("Poller::createGlyph","XPutImage on pixmap %d,%d,%d,%d.\n", + 0, 0, width, height);*/ + XPutImage(display_, bitmap, glyphGC, image, 0, 0, 0, 0, width, height); + XFree(image); + + return bitmap; +} +#endif /* defined(__CYGWIN32__) || defined(WIN32) */ |