display.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. /*
  2. * The Python Imaging Library.
  3. *
  4. * display support (and other windows-related stuff)
  5. *
  6. * History:
  7. * 1996-05-13 fl Windows DIB support
  8. * 1996-05-21 fl Added palette stuff
  9. * 1996-05-28 fl Added display_mode stuff
  10. * 1997-09-21 fl Added draw primitive
  11. * 2001-09-17 fl Added ImagingGrabScreen (from _grabscreen.c)
  12. * 2002-05-12 fl Added ImagingListWindows
  13. * 2002-11-19 fl Added clipboard support
  14. * 2002-11-25 fl Added GetDC/ReleaseDC helpers
  15. * 2003-05-21 fl Added create window support (including window callback)
  16. * 2003-09-05 fl Added fromstring/tostring methods
  17. * 2009-03-14 fl Added WMF support (from pilwmf)
  18. *
  19. * Copyright (c) 1997-2003 by Secret Labs AB.
  20. * Copyright (c) 1996-1997 by Fredrik Lundh.
  21. *
  22. * See the README file for information on usage and redistribution.
  23. */
  24. #define PY_SSIZE_T_CLEAN
  25. #include "Python.h"
  26. #include "libImaging/Imaging.h"
  27. /* -------------------------------------------------------------------- */
  28. /* Windows DIB support */
  29. #ifdef _WIN32
  30. #include "libImaging/ImDib.h"
  31. #if SIZEOF_VOID_P == 8
  32. #define F_HANDLE "K"
  33. #else
  34. #define F_HANDLE "k"
  35. #endif
  36. typedef struct {
  37. PyObject_HEAD ImagingDIB dib;
  38. } ImagingDisplayObject;
  39. static PyTypeObject ImagingDisplayType;
  40. static ImagingDisplayObject *
  41. _new(const char *mode, int xsize, int ysize) {
  42. ImagingDisplayObject *display;
  43. if (PyType_Ready(&ImagingDisplayType) < 0) {
  44. return NULL;
  45. }
  46. display = PyObject_New(ImagingDisplayObject, &ImagingDisplayType);
  47. if (display == NULL) {
  48. return NULL;
  49. }
  50. display->dib = ImagingNewDIB(mode, xsize, ysize);
  51. if (!display->dib) {
  52. Py_DECREF(display);
  53. return NULL;
  54. }
  55. return display;
  56. }
  57. static void
  58. _delete(ImagingDisplayObject *display) {
  59. if (display->dib) {
  60. ImagingDeleteDIB(display->dib);
  61. }
  62. PyObject_Del(display);
  63. }
  64. static PyObject *
  65. _expose(ImagingDisplayObject *display, PyObject *args) {
  66. HDC hdc;
  67. if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) {
  68. return NULL;
  69. }
  70. ImagingExposeDIB(display->dib, hdc);
  71. Py_INCREF(Py_None);
  72. return Py_None;
  73. }
  74. static PyObject *
  75. _draw(ImagingDisplayObject *display, PyObject *args) {
  76. HDC hdc;
  77. int dst[4];
  78. int src[4];
  79. if (!PyArg_ParseTuple(
  80. args,
  81. F_HANDLE "(iiii)(iiii)",
  82. &hdc,
  83. dst + 0,
  84. dst + 1,
  85. dst + 2,
  86. dst + 3,
  87. src + 0,
  88. src + 1,
  89. src + 2,
  90. src + 3)) {
  91. return NULL;
  92. }
  93. ImagingDrawDIB(display->dib, hdc, dst, src);
  94. Py_INCREF(Py_None);
  95. return Py_None;
  96. }
  97. extern Imaging
  98. PyImaging_AsImaging(PyObject *op);
  99. static PyObject *
  100. _paste(ImagingDisplayObject *display, PyObject *args) {
  101. Imaging im;
  102. PyObject *op;
  103. int xy[4];
  104. xy[0] = xy[1] = xy[2] = xy[3] = 0;
  105. if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy + 0, xy + 1, xy + 2, xy + 3)) {
  106. return NULL;
  107. }
  108. im = PyImaging_AsImaging(op);
  109. if (!im) {
  110. return NULL;
  111. }
  112. if (xy[2] <= xy[0]) {
  113. xy[2] = xy[0] + im->xsize;
  114. }
  115. if (xy[3] <= xy[1]) {
  116. xy[3] = xy[1] + im->ysize;
  117. }
  118. ImagingPasteDIB(display->dib, im, xy);
  119. Py_INCREF(Py_None);
  120. return Py_None;
  121. }
  122. static PyObject *
  123. _query_palette(ImagingDisplayObject *display, PyObject *args) {
  124. HDC hdc;
  125. int status;
  126. if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) {
  127. return NULL;
  128. }
  129. status = ImagingQueryPaletteDIB(display->dib, hdc);
  130. return Py_BuildValue("i", status);
  131. }
  132. static PyObject *
  133. _getdc(ImagingDisplayObject *display, PyObject *args) {
  134. HWND window;
  135. HDC dc;
  136. if (!PyArg_ParseTuple(args, F_HANDLE, &window)) {
  137. return NULL;
  138. }
  139. dc = GetDC(window);
  140. if (!dc) {
  141. PyErr_SetString(PyExc_OSError, "cannot create dc");
  142. return NULL;
  143. }
  144. return Py_BuildValue(F_HANDLE, dc);
  145. }
  146. static PyObject *
  147. _releasedc(ImagingDisplayObject *display, PyObject *args) {
  148. HWND window;
  149. HDC dc;
  150. if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &window, &dc)) {
  151. return NULL;
  152. }
  153. ReleaseDC(window, dc);
  154. Py_INCREF(Py_None);
  155. return Py_None;
  156. }
  157. static PyObject *
  158. _frombytes(ImagingDisplayObject *display, PyObject *args) {
  159. Py_buffer buffer;
  160. if (!PyArg_ParseTuple(args, "y*:frombytes", &buffer)) {
  161. return NULL;
  162. }
  163. if (display->dib->ysize * display->dib->linesize != buffer.len) {
  164. PyBuffer_Release(&buffer);
  165. PyErr_SetString(PyExc_ValueError, "wrong size");
  166. return NULL;
  167. }
  168. memcpy(display->dib->bits, buffer.buf, buffer.len);
  169. PyBuffer_Release(&buffer);
  170. Py_INCREF(Py_None);
  171. return Py_None;
  172. }
  173. static PyObject *
  174. _tobytes(ImagingDisplayObject *display, PyObject *args) {
  175. if (!PyArg_ParseTuple(args, ":tobytes")) {
  176. return NULL;
  177. }
  178. return PyBytes_FromStringAndSize(
  179. display->dib->bits, display->dib->ysize * display->dib->linesize);
  180. }
  181. static struct PyMethodDef methods[] = {
  182. {"draw", (PyCFunction)_draw, METH_VARARGS},
  183. {"expose", (PyCFunction)_expose, METH_VARARGS},
  184. {"paste", (PyCFunction)_paste, METH_VARARGS},
  185. {"query_palette", (PyCFunction)_query_palette, METH_VARARGS},
  186. {"getdc", (PyCFunction)_getdc, METH_VARARGS},
  187. {"releasedc", (PyCFunction)_releasedc, METH_VARARGS},
  188. {"frombytes", (PyCFunction)_frombytes, METH_VARARGS},
  189. {"tobytes", (PyCFunction)_tobytes, METH_VARARGS},
  190. {NULL, NULL} /* sentinel */
  191. };
  192. static PyObject *
  193. _getattr_mode(ImagingDisplayObject *self, void *closure) {
  194. return Py_BuildValue("s", self->dib->mode);
  195. }
  196. static PyObject *
  197. _getattr_size(ImagingDisplayObject *self, void *closure) {
  198. return Py_BuildValue("ii", self->dib->xsize, self->dib->ysize);
  199. }
  200. static struct PyGetSetDef getsetters[] = {
  201. {"mode", (getter)_getattr_mode}, {"size", (getter)_getattr_size}, {NULL}};
  202. static PyTypeObject ImagingDisplayType = {
  203. PyVarObject_HEAD_INIT(NULL, 0) "ImagingDisplay", /*tp_name*/
  204. sizeof(ImagingDisplayObject), /*tp_basicsize*/
  205. 0, /*tp_itemsize*/
  206. /* methods */
  207. (destructor)_delete, /*tp_dealloc*/
  208. 0, /*tp_vectorcall_offset*/
  209. 0, /*tp_getattr*/
  210. 0, /*tp_setattr*/
  211. 0, /*tp_as_async*/
  212. 0, /*tp_repr*/
  213. 0, /*tp_as_number*/
  214. 0, /*tp_as_sequence*/
  215. 0, /*tp_as_mapping*/
  216. 0, /*tp_hash*/
  217. 0, /*tp_call*/
  218. 0, /*tp_str*/
  219. 0, /*tp_getattro*/
  220. 0, /*tp_setattro*/
  221. 0, /*tp_as_buffer*/
  222. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  223. 0, /*tp_doc*/
  224. 0, /*tp_traverse*/
  225. 0, /*tp_clear*/
  226. 0, /*tp_richcompare*/
  227. 0, /*tp_weaklistoffset*/
  228. 0, /*tp_iter*/
  229. 0, /*tp_iternext*/
  230. methods, /*tp_methods*/
  231. 0, /*tp_members*/
  232. getsetters, /*tp_getset*/
  233. };
  234. PyObject *
  235. PyImaging_DisplayWin32(PyObject *self, PyObject *args) {
  236. ImagingDisplayObject *display;
  237. char *mode;
  238. int xsize, ysize;
  239. if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize)) {
  240. return NULL;
  241. }
  242. display = _new(mode, xsize, ysize);
  243. if (display == NULL) {
  244. return NULL;
  245. }
  246. return (PyObject *)display;
  247. }
  248. PyObject *
  249. PyImaging_DisplayModeWin32(PyObject *self, PyObject *args) {
  250. char *mode;
  251. int size[2];
  252. mode = ImagingGetModeDIB(size);
  253. return Py_BuildValue("s(ii)", mode, size[0], size[1]);
  254. }
  255. /* -------------------------------------------------------------------- */
  256. /* Windows screen grabber */
  257. typedef HANDLE(__stdcall *Func_SetThreadDpiAwarenessContext)(HANDLE);
  258. PyObject *
  259. PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) {
  260. int x = 0, y = 0, width, height;
  261. int includeLayeredWindows = 0, all_screens = 0;
  262. HBITMAP bitmap;
  263. BITMAPCOREHEADER core;
  264. HDC screen, screen_copy;
  265. DWORD rop;
  266. PyObject *buffer;
  267. HANDLE dpiAwareness;
  268. HMODULE user32;
  269. Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function;
  270. if (!PyArg_ParseTuple(args, "|ii", &includeLayeredWindows, &all_screens)) {
  271. return NULL;
  272. }
  273. /* step 1: create a memory DC large enough to hold the
  274. entire screen */
  275. screen = CreateDC("DISPLAY", NULL, NULL, NULL);
  276. screen_copy = CreateCompatibleDC(screen);
  277. // added in Windows 10 (1607)
  278. // loaded dynamically to avoid link errors
  279. user32 = LoadLibraryA("User32.dll");
  280. SetThreadDpiAwarenessContext_function =
  281. (Func_SetThreadDpiAwarenessContext)GetProcAddress(
  282. user32, "SetThreadDpiAwarenessContext");
  283. if (SetThreadDpiAwarenessContext_function != NULL) {
  284. // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3)
  285. dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE)-3);
  286. }
  287. if (all_screens) {
  288. x = GetSystemMetrics(SM_XVIRTUALSCREEN);
  289. y = GetSystemMetrics(SM_YVIRTUALSCREEN);
  290. width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
  291. height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
  292. } else {
  293. width = GetDeviceCaps(screen, HORZRES);
  294. height = GetDeviceCaps(screen, VERTRES);
  295. }
  296. if (SetThreadDpiAwarenessContext_function != NULL) {
  297. SetThreadDpiAwarenessContext_function(dpiAwareness);
  298. }
  299. FreeLibrary(user32);
  300. bitmap = CreateCompatibleBitmap(screen, width, height);
  301. if (!bitmap) {
  302. goto error;
  303. }
  304. if (!SelectObject(screen_copy, bitmap)) {
  305. goto error;
  306. }
  307. /* step 2: copy bits into memory DC bitmap */
  308. rop = SRCCOPY;
  309. if (includeLayeredWindows) {
  310. rop |= CAPTUREBLT;
  311. }
  312. if (!BitBlt(screen_copy, 0, 0, width, height, screen, x, y, rop)) {
  313. goto error;
  314. }
  315. /* step 3: extract bits from bitmap */
  316. buffer = PyBytes_FromStringAndSize(NULL, height * ((width * 3 + 3) & -4));
  317. if (!buffer) {
  318. return NULL;
  319. }
  320. core.bcSize = sizeof(core);
  321. core.bcWidth = width;
  322. core.bcHeight = height;
  323. core.bcPlanes = 1;
  324. core.bcBitCount = 24;
  325. if (!GetDIBits(
  326. screen_copy,
  327. bitmap,
  328. 0,
  329. height,
  330. PyBytes_AS_STRING(buffer),
  331. (BITMAPINFO *)&core,
  332. DIB_RGB_COLORS)) {
  333. goto error;
  334. }
  335. DeleteObject(bitmap);
  336. DeleteDC(screen_copy);
  337. DeleteDC(screen);
  338. return Py_BuildValue("(ii)(ii)N", x, y, width, height, buffer);
  339. error:
  340. PyErr_SetString(PyExc_OSError, "screen grab failed");
  341. DeleteDC(screen_copy);
  342. DeleteDC(screen);
  343. return NULL;
  344. }
  345. /* -------------------------------------------------------------------- */
  346. /* Windows clipboard grabber */
  347. PyObject *
  348. PyImaging_GrabClipboardWin32(PyObject *self, PyObject *args) {
  349. int clip;
  350. HANDLE handle = NULL;
  351. int size;
  352. void *data;
  353. PyObject *result;
  354. UINT format;
  355. UINT formats[] = {CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0};
  356. LPCSTR format_names[] = {"DIB", "DIB", "file", "png", NULL};
  357. if (!OpenClipboard(NULL)) {
  358. // Maybe the clipboard is temporarily in use by another process.
  359. // Wait and try again
  360. Sleep(500);
  361. if (!OpenClipboard(NULL)) {
  362. PyErr_SetString(PyExc_OSError, "failed to open clipboard");
  363. return NULL;
  364. }
  365. }
  366. // find best format as set by clipboard owner
  367. format = 0;
  368. while (!handle && (format = EnumClipboardFormats(format))) {
  369. for (UINT i = 0; formats[i] != 0; i++) {
  370. if (format == formats[i]) {
  371. handle = GetClipboardData(format);
  372. format = i;
  373. break;
  374. }
  375. }
  376. }
  377. if (!handle) {
  378. CloseClipboard();
  379. return Py_BuildValue("zO", NULL, Py_None);
  380. }
  381. data = GlobalLock(handle);
  382. size = GlobalSize(handle);
  383. result = PyBytes_FromStringAndSize(data, size);
  384. GlobalUnlock(handle);
  385. CloseClipboard();
  386. return Py_BuildValue("zN", format_names[format], result);
  387. }
  388. /* -------------------------------------------------------------------- */
  389. /* Windows class */
  390. #ifndef WM_MOUSEWHEEL
  391. #define WM_MOUSEWHEEL 522
  392. #endif
  393. static int mainloop = 0;
  394. static void
  395. callback_error(const char *handler) {
  396. PyObject *sys_stderr;
  397. sys_stderr = PySys_GetObject("stderr");
  398. if (sys_stderr) {
  399. PyFile_WriteString("*** ImageWin: error in ", sys_stderr);
  400. PyFile_WriteString((char *)handler, sys_stderr);
  401. PyFile_WriteString(":\n", sys_stderr);
  402. }
  403. PyErr_Print();
  404. PyErr_Clear();
  405. }
  406. static LRESULT CALLBACK
  407. windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
  408. PAINTSTRUCT ps;
  409. PyObject *callback = NULL;
  410. PyObject *result;
  411. PyThreadState *threadstate;
  412. PyThreadState *current_threadstate;
  413. HDC dc;
  414. RECT rect;
  415. LRESULT status = 0;
  416. /* set up threadstate for messages that calls back into python */
  417. switch (message) {
  418. case WM_CREATE:
  419. mainloop++;
  420. break;
  421. case WM_DESTROY:
  422. mainloop--;
  423. /* fall through... */
  424. case WM_PAINT:
  425. case WM_SIZE:
  426. callback = (PyObject *)GetWindowLongPtr(wnd, 0);
  427. if (callback) {
  428. threadstate =
  429. (PyThreadState *)GetWindowLongPtr(wnd, sizeof(PyObject *));
  430. current_threadstate = PyThreadState_Swap(NULL);
  431. PyEval_RestoreThread(threadstate);
  432. } else {
  433. return DefWindowProc(wnd, message, wParam, lParam);
  434. }
  435. }
  436. /* process message */
  437. switch (message) {
  438. case WM_PAINT:
  439. /* redraw (part of) window. this generates a WCK-style
  440. damage/clear/repair cascade */
  441. BeginPaint(wnd, &ps);
  442. dc = GetDC(wnd);
  443. GetWindowRect(wnd, &rect); /* in screen coordinates */
  444. result = PyObject_CallFunction(
  445. callback,
  446. "siiii",
  447. "damage",
  448. ps.rcPaint.left,
  449. ps.rcPaint.top,
  450. ps.rcPaint.right,
  451. ps.rcPaint.bottom);
  452. if (result) {
  453. Py_DECREF(result);
  454. } else {
  455. callback_error("window damage callback");
  456. }
  457. result = PyObject_CallFunction(
  458. callback,
  459. "s" F_HANDLE "iiii",
  460. "clear",
  461. dc,
  462. 0,
  463. 0,
  464. rect.right - rect.left,
  465. rect.bottom - rect.top);
  466. if (result) {
  467. Py_DECREF(result);
  468. } else {
  469. callback_error("window clear callback");
  470. }
  471. result = PyObject_CallFunction(
  472. callback,
  473. "s" F_HANDLE "iiii",
  474. "repair",
  475. dc,
  476. 0,
  477. 0,
  478. rect.right - rect.left,
  479. rect.bottom - rect.top);
  480. if (result) {
  481. Py_DECREF(result);
  482. } else {
  483. callback_error("window repair callback");
  484. }
  485. ReleaseDC(wnd, dc);
  486. EndPaint(wnd, &ps);
  487. break;
  488. case WM_SIZE:
  489. /* resize window */
  490. result = PyObject_CallFunction(
  491. callback, "sii", "resize", LOWORD(lParam), HIWORD(lParam));
  492. if (result) {
  493. InvalidateRect(wnd, NULL, 1);
  494. Py_DECREF(result);
  495. } else {
  496. callback_error("window resize callback");
  497. }
  498. break;
  499. case WM_DESTROY:
  500. /* destroy window */
  501. result = PyObject_CallFunction(callback, "s", "destroy");
  502. if (result) {
  503. Py_DECREF(result);
  504. } else {
  505. callback_error("window destroy callback");
  506. }
  507. Py_DECREF(callback);
  508. break;
  509. default:
  510. status = DefWindowProc(wnd, message, wParam, lParam);
  511. }
  512. if (callback) {
  513. /* restore thread state */
  514. PyEval_SaveThread();
  515. PyThreadState_Swap(threadstate);
  516. }
  517. return status;
  518. }
  519. PyObject *
  520. PyImaging_CreateWindowWin32(PyObject *self, PyObject *args) {
  521. HWND wnd;
  522. WNDCLASS windowClass;
  523. char *title;
  524. PyObject *callback;
  525. int width = 0, height = 0;
  526. if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height)) {
  527. return NULL;
  528. }
  529. if (width <= 0) {
  530. width = CW_USEDEFAULT;
  531. }
  532. if (height <= 0) {
  533. height = CW_USEDEFAULT;
  534. }
  535. /* register toplevel window class */
  536. windowClass.style = CS_CLASSDC;
  537. windowClass.cbClsExtra = 0;
  538. windowClass.cbWndExtra = sizeof(PyObject *) + sizeof(PyThreadState *);
  539. windowClass.hInstance = GetModuleHandle(NULL);
  540. /* windowClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); */
  541. windowClass.hbrBackground = NULL;
  542. windowClass.lpszMenuName = NULL;
  543. windowClass.lpszClassName = "pilWindow";
  544. windowClass.lpfnWndProc = windowCallback;
  545. windowClass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(1));
  546. windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); /* CROSS? */
  547. RegisterClass(&windowClass); /* FIXME: check return status */
  548. wnd = CreateWindowEx(
  549. 0,
  550. windowClass.lpszClassName,
  551. title,
  552. WS_OVERLAPPEDWINDOW,
  553. CW_USEDEFAULT,
  554. CW_USEDEFAULT,
  555. width,
  556. height,
  557. HWND_DESKTOP,
  558. NULL,
  559. NULL,
  560. NULL);
  561. if (!wnd) {
  562. PyErr_SetString(PyExc_OSError, "failed to create window");
  563. return NULL;
  564. }
  565. /* register window callback */
  566. Py_INCREF(callback);
  567. SetWindowLongPtr(wnd, 0, (LONG_PTR)callback);
  568. SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR)PyThreadState_Get());
  569. Py_BEGIN_ALLOW_THREADS ShowWindow(wnd, SW_SHOWNORMAL);
  570. SetForegroundWindow(wnd); /* to make sure it's visible */
  571. Py_END_ALLOW_THREADS
  572. return Py_BuildValue(F_HANDLE, wnd);
  573. }
  574. PyObject *
  575. PyImaging_EventLoopWin32(PyObject *self, PyObject *args) {
  576. MSG msg;
  577. Py_BEGIN_ALLOW_THREADS while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
  578. TranslateMessage(&msg);
  579. DispatchMessage(&msg);
  580. }
  581. Py_END_ALLOW_THREADS
  582. Py_INCREF(Py_None);
  583. return Py_None;
  584. }
  585. /* -------------------------------------------------------------------- */
  586. /* windows WMF renderer */
  587. #define GET32(p, o) ((DWORD *)(p + o))[0]
  588. PyObject *
  589. PyImaging_DrawWmf(PyObject *self, PyObject *args) {
  590. HBITMAP bitmap;
  591. HENHMETAFILE meta;
  592. BITMAPCOREHEADER core;
  593. HDC dc;
  594. RECT rect;
  595. PyObject *buffer = NULL;
  596. char *ptr;
  597. char *data;
  598. Py_ssize_t datasize;
  599. int width, height;
  600. int x0, y0, x1, y1;
  601. if (!PyArg_ParseTuple(
  602. args,
  603. "y#(ii)(iiii):_load",
  604. &data,
  605. &datasize,
  606. &width,
  607. &height,
  608. &x0,
  609. &x1,
  610. &y0,
  611. &y1)) {
  612. return NULL;
  613. }
  614. /* step 1: copy metafile contents into METAFILE object */
  615. if (datasize > 22 && GET32(data, 0) == 0x9ac6cdd7) {
  616. /* placeable windows metafile (22-byte aldus header) */
  617. meta = SetWinMetaFileBits(datasize - 22, data + 22, NULL, NULL);
  618. } else if (datasize > 80 && GET32(data, 0) == 1 && GET32(data, 40) == 0x464d4520) {
  619. /* enhanced metafile */
  620. meta = SetEnhMetaFileBits(datasize, data);
  621. } else {
  622. /* unknown meta format */
  623. meta = NULL;
  624. }
  625. if (!meta) {
  626. PyErr_SetString(PyExc_OSError, "cannot load metafile");
  627. return NULL;
  628. }
  629. /* step 2: create bitmap */
  630. core.bcSize = sizeof(core);
  631. core.bcWidth = width;
  632. core.bcHeight = height;
  633. core.bcPlanes = 1;
  634. core.bcBitCount = 24;
  635. dc = CreateCompatibleDC(NULL);
  636. bitmap = CreateDIBSection(dc, (BITMAPINFO *)&core, DIB_RGB_COLORS, &ptr, NULL, 0);
  637. if (!bitmap) {
  638. PyErr_SetString(PyExc_OSError, "cannot create bitmap");
  639. goto error;
  640. }
  641. if (!SelectObject(dc, bitmap)) {
  642. PyErr_SetString(PyExc_OSError, "cannot select bitmap");
  643. goto error;
  644. }
  645. /* step 3: render metafile into bitmap */
  646. rect.left = rect.top = 0;
  647. rect.right = width;
  648. rect.bottom = height;
  649. /* FIXME: make background transparent? configurable? */
  650. FillRect(dc, &rect, GetStockObject(WHITE_BRUSH));
  651. if (!PlayEnhMetaFile(dc, meta, &rect)) {
  652. PyErr_SetString(PyExc_OSError, "cannot render metafile");
  653. goto error;
  654. }
  655. /* step 4: extract bits from bitmap */
  656. GdiFlush();
  657. buffer = PyBytes_FromStringAndSize(ptr, height * ((width * 3 + 3) & -4));
  658. error:
  659. DeleteEnhMetaFile(meta);
  660. if (bitmap) {
  661. DeleteObject(bitmap);
  662. }
  663. DeleteDC(dc);
  664. return buffer;
  665. }
  666. #endif /* _WIN32 */
  667. /* -------------------------------------------------------------------- */
  668. /* X11 support */
  669. #ifdef HAVE_XCB
  670. #error #include <xcb/xcb.h>
  671. /* -------------------------------------------------------------------- */
  672. /* X11 screen grabber */
  673. PyObject *
  674. PyImaging_GrabScreenX11(PyObject *self, PyObject *args) {
  675. int width, height;
  676. char *display_name;
  677. xcb_connection_t *connection;
  678. int screen_number;
  679. xcb_screen_iterator_t iter;
  680. xcb_screen_t *screen = NULL;
  681. xcb_get_image_reply_t *reply;
  682. xcb_generic_error_t *error;
  683. PyObject *buffer = NULL;
  684. if (!PyArg_ParseTuple(args, "|z", &display_name)) {
  685. return NULL;
  686. }
  687. /* connect to X and get screen data */
  688. connection = xcb_connect(display_name, &screen_number);
  689. if (xcb_connection_has_error(connection)) {
  690. PyErr_Format(
  691. PyExc_OSError,
  692. "X connection failed: error %i",
  693. xcb_connection_has_error(connection));
  694. xcb_disconnect(connection);
  695. return NULL;
  696. }
  697. iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
  698. for (; iter.rem; --screen_number, xcb_screen_next(&iter)) {
  699. if (screen_number == 0) {
  700. screen = iter.data;
  701. break;
  702. }
  703. }
  704. if (screen == NULL || screen->root == 0) {
  705. // this case is usually caught with "X connection failed: error 6" above
  706. xcb_disconnect(connection);
  707. PyErr_SetString(PyExc_OSError, "X screen not found");
  708. return NULL;
  709. }
  710. width = screen->width_in_pixels;
  711. height = screen->height_in_pixels;
  712. /* get image data */
  713. reply = xcb_get_image_reply(
  714. connection,
  715. xcb_get_image(
  716. connection,
  717. XCB_IMAGE_FORMAT_Z_PIXMAP,
  718. screen->root,
  719. 0,
  720. 0,
  721. width,
  722. height,
  723. 0x00ffffff),
  724. &error);
  725. if (reply == NULL) {
  726. PyErr_Format(
  727. PyExc_OSError,
  728. "X get_image failed: error %i (%i, %i, %i)",
  729. error->error_code,
  730. error->major_code,
  731. error->minor_code,
  732. error->resource_id);
  733. free(error);
  734. xcb_disconnect(connection);
  735. return NULL;
  736. }
  737. /* store data in Python buffer */
  738. if (reply->depth == 24) {
  739. buffer = PyBytes_FromStringAndSize(
  740. (char *)xcb_get_image_data(reply), xcb_get_image_data_length(reply));
  741. } else {
  742. PyErr_Format(PyExc_OSError, "unsupported bit depth: %i", reply->depth);
  743. }
  744. free(reply);
  745. xcb_disconnect(connection);
  746. if (!buffer) {
  747. return NULL;
  748. }
  749. return Py_BuildValue("(ii)N", width, height, buffer);
  750. }
  751. #endif /* HAVE_XCB */