dmxwindow.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. /*
  2. * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
  3. *
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation on the rights to use, copy, modify, merge,
  10. * publish, distribute, sublicense, and/or sell copies of the Software,
  11. * and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial
  16. * portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
  22. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  23. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  25. * SOFTWARE.
  26. */
  27. /*
  28. * Authors:
  29. * Kevin E. Martin <kem@redhat.com>
  30. *
  31. */
  32. /** \file
  33. * This file provides support for window-related functions. */
  34. #ifdef HAVE_DMX_CONFIG_H
  35. #include <dmx-config.h>
  36. #endif
  37. #include "dmx.h"
  38. #include "dmxsync.h"
  39. #include "dmxwindow.h"
  40. #include "dmxpixmap.h"
  41. #include "dmxcmap.h"
  42. #include "dmxvisual.h"
  43. #include "dmxinput.h"
  44. #include "dmxextension.h"
  45. #include "dmxpict.h"
  46. #include "windowstr.h"
  47. static void dmxDoRestackWindow(WindowPtr pWindow);
  48. static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
  49. unsigned long *mask,
  50. XSetWindowAttributes * attribs);
  51. static void dmxDoSetShape(WindowPtr pWindow);
  52. /** Initialize the private area for the window functions. */
  53. Bool
  54. dmxInitWindow(ScreenPtr pScreen)
  55. {
  56. if (!dixRegisterPrivateKey
  57. (&dmxWinPrivateKeyRec, PRIVATE_WINDOW, sizeof(dmxWinPrivRec)))
  58. return FALSE;
  59. return TRUE;
  60. }
  61. Window
  62. dmxCreateRootWindow(WindowPtr pWindow)
  63. {
  64. ScreenPtr pScreen = pWindow->drawable.pScreen;
  65. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  66. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  67. Window parent;
  68. Visual *visual;
  69. unsigned long mask;
  70. XSetWindowAttributes attribs;
  71. ColormapPtr pCmap;
  72. dmxColormapPrivPtr pCmapPriv;
  73. /* Create root window */
  74. parent = dmxScreen->scrnWin; /* This is our "Screen" window */
  75. visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual;
  76. dixLookupResourceByType((void **) &pCmap, wColormap(pWindow),
  77. RT_COLORMAP, NullClient, DixUnknownAccess);
  78. pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
  79. mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel;
  80. attribs.event_mask = ExposureMask;
  81. attribs.backing_store = NotUseful;
  82. attribs.colormap = pCmapPriv->cmap;
  83. attribs.border_pixel = 0;
  84. /* Incorporate new attributes, if needed */
  85. if (pWinPriv->attribMask) {
  86. dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
  87. mask |= pWinPriv->attribMask;
  88. }
  89. return XCreateWindow(dmxScreen->beDisplay,
  90. parent,
  91. pWindow->origin.x - wBorderWidth(pWindow),
  92. pWindow->origin.y - wBorderWidth(pWindow),
  93. pWindow->drawable.width,
  94. pWindow->drawable.height,
  95. pWindow->borderWidth,
  96. pWindow->drawable.depth,
  97. pWindow->drawable.class, visual, mask, &attribs);
  98. }
  99. /** Change the location and size of the "screen" window. Called from
  100. * dmxextension.c dmxConfigureScreenWindow(). */
  101. void
  102. dmxResizeScreenWindow(ScreenPtr pScreen, int x, int y, int w, int h)
  103. {
  104. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  105. unsigned int m;
  106. XWindowChanges c;
  107. if (!dmxScreen->beDisplay)
  108. return;
  109. /* Handle resizing on back-end server */
  110. m = CWX | CWY | CWWidth | CWHeight;
  111. c.x = x;
  112. c.y = y;
  113. c.width = w;
  114. c.height = h;
  115. XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c);
  116. dmxSync(dmxScreen, False);
  117. }
  118. /** Change the location and size of the "root" window. Called from
  119. * #dmxCreateWindow. */
  120. void
  121. dmxResizeRootWindow(WindowPtr pRoot, int x, int y, int w, int h)
  122. {
  123. DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum];
  124. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
  125. unsigned int m;
  126. XWindowChanges c;
  127. /* Handle resizing on back-end server */
  128. if (dmxScreen->beDisplay) {
  129. m = CWX | CWY | CWWidth | CWHeight;
  130. c.x = x;
  131. c.y = y;
  132. c.width = (w > 0) ? w : 1;
  133. c.height = (h > 0) ? h : 1;
  134. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  135. }
  136. if (w == 0 || h == 0) {
  137. if (pWinPriv->mapped) {
  138. if (dmxScreen->beDisplay)
  139. XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
  140. pWinPriv->mapped = FALSE;
  141. }
  142. }
  143. else if (!pWinPriv->mapped) {
  144. if (dmxScreen->beDisplay)
  145. XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
  146. pWinPriv->mapped = TRUE;
  147. }
  148. if (dmxScreen->beDisplay)
  149. dmxSync(dmxScreen, False);
  150. }
  151. void
  152. dmxGetDefaultWindowAttributes(WindowPtr pWindow,
  153. Colormap * cmap, Visual ** visual)
  154. {
  155. ScreenPtr pScreen = pWindow->drawable.pScreen;
  156. if (pWindow->drawable.class != InputOnly &&
  157. pWindow->optional &&
  158. pWindow->optional->visual != wVisual(pWindow->parent)) {
  159. /* Find the matching visual */
  160. *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow));
  161. /* Handle optional colormaps */
  162. if (pWindow->optional->colormap) {
  163. ColormapPtr pCmap;
  164. dmxColormapPrivPtr pCmapPriv;
  165. dixLookupResourceByType((void **) &pCmap, wColormap(pWindow),
  166. RT_COLORMAP, NullClient, DixUnknownAccess);
  167. pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
  168. *cmap = pCmapPriv->cmap;
  169. }
  170. else {
  171. *cmap = dmxColormapFromDefaultVisual(pScreen, *visual);
  172. }
  173. }
  174. else {
  175. *visual = CopyFromParent;
  176. *cmap = (Colormap) 0;
  177. }
  178. }
  179. static Window
  180. dmxCreateNonRootWindow(WindowPtr pWindow)
  181. {
  182. ScreenPtr pScreen = pWindow->drawable.pScreen;
  183. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  184. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  185. Window parent;
  186. unsigned long mask = 0L;
  187. XSetWindowAttributes attribs;
  188. dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
  189. /* Create window on back-end server */
  190. parent = pParentPriv->window;
  191. /* The parent won't exist if this call to CreateNonRootWindow came
  192. from ReparentWindow and the grandparent window has not yet been
  193. created */
  194. if (!parent) {
  195. dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
  196. parent = pParentPriv->window;
  197. }
  198. /* Incorporate new attributes, if needed */
  199. if (pWinPriv->attribMask) {
  200. dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
  201. mask |= pWinPriv->attribMask;
  202. }
  203. /* Add in default attributes */
  204. if (pWindow->drawable.class != InputOnly) {
  205. mask |= CWBackingStore;
  206. attribs.backing_store = NotUseful;
  207. if (!(mask & CWColormap) && pWinPriv->cmap) {
  208. mask |= CWColormap;
  209. attribs.colormap = pWinPriv->cmap;
  210. if (!(mask & CWBorderPixel)) {
  211. mask |= CWBorderPixel;
  212. attribs.border_pixel = 0;
  213. }
  214. }
  215. }
  216. /* Handle case where subwindows are being mapped, but created out of
  217. order -- if current window has a previous sibling, then it cannot
  218. be created on top of the stack, so we must restack the windows */
  219. pWinPriv->restacked = (pWindow->prevSib != NullWindow);
  220. return XCreateWindow(dmxScreen->beDisplay,
  221. parent,
  222. pWindow->origin.x - wBorderWidth(pWindow),
  223. pWindow->origin.y - wBorderWidth(pWindow),
  224. pWindow->drawable.width,
  225. pWindow->drawable.height,
  226. pWindow->borderWidth,
  227. pWindow->drawable.depth,
  228. pWindow->drawable.class,
  229. pWinPriv->visual, mask, &attribs);
  230. }
  231. /** This function handles lazy window creation and realization. Window
  232. * creation is handled by #dmxCreateNonRootWindow(). It also handles
  233. * any stacking changes that have occured since the window was
  234. * originally created by calling #dmxDoRestackWindow(). If the window
  235. * is shaped, the shape is set on the back-end server by calling
  236. * #dmxDoSetShape(), and if the window has pictures (from RENDER)
  237. * associated with it, those pictures are created on the back-end
  238. * server by calling #dmxCreatePictureList(). If \a doSync is TRUE,
  239. * then #dmxSync() is called. */
  240. void
  241. dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync)
  242. {
  243. ScreenPtr pScreen = pWindow->drawable.pScreen;
  244. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  245. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  246. if (!dmxScreen->beDisplay)
  247. return;
  248. pWinPriv->window = dmxCreateNonRootWindow(pWindow);
  249. if (pWinPriv->restacked)
  250. dmxDoRestackWindow(pWindow);
  251. if (pWinPriv->isShaped)
  252. dmxDoSetShape(pWindow);
  253. if (pWinPriv->hasPict)
  254. dmxCreatePictureList(pWindow);
  255. if (pWinPriv->mapped)
  256. XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
  257. if (doSync)
  258. dmxSync(dmxScreen, False);
  259. }
  260. /** Create \a pWindow on the back-end server. If the lazy window
  261. * creation optimization is enabled, then the actual creation and
  262. * realization of the window is handled by
  263. * #dmxCreateAndRealizeWindow(). */
  264. Bool
  265. dmxCreateWindow(WindowPtr pWindow)
  266. {
  267. ScreenPtr pScreen = pWindow->drawable.pScreen;
  268. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  269. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  270. Bool ret = TRUE;
  271. DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
  272. #if 0
  273. if (pScreen->CreateWindow)
  274. ret = pScreen->CreateWindow(pWindow);
  275. #endif
  276. /* Set up the defaults */
  277. pWinPriv->window = (Window) 0;
  278. pWinPriv->offscreen = TRUE;
  279. pWinPriv->mapped = FALSE;
  280. pWinPriv->restacked = FALSE;
  281. pWinPriv->attribMask = 0;
  282. pWinPriv->isShaped = FALSE;
  283. pWinPriv->hasPict = FALSE;
  284. #ifdef GLXEXT
  285. pWinPriv->swapGroup = NULL;
  286. pWinPriv->barrier = 0;
  287. #endif
  288. if (dmxScreen->beDisplay) {
  289. /* Only create the root window at this stage -- non-root windows are
  290. created when they are mapped and are on-screen */
  291. if (!pWindow->parent) {
  292. dmxScreen->rootWin = pWinPriv->window
  293. = dmxCreateRootWindow(pWindow);
  294. if (dmxScreen->scrnX != dmxScreen->rootX
  295. || dmxScreen->scrnY != dmxScreen->rootY
  296. || dmxScreen->scrnWidth != dmxScreen->rootWidth
  297. || dmxScreen->scrnHeight != dmxScreen->rootHeight) {
  298. dmxResizeRootWindow(pWindow,
  299. dmxScreen->rootX,
  300. dmxScreen->rootY,
  301. dmxScreen->rootWidth,
  302. dmxScreen->rootHeight);
  303. dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index],
  304. dmxScreen->rootX,
  305. dmxScreen->rootY,
  306. dmxScreen->rootWidth,
  307. dmxScreen->rootHeight);
  308. pWindow->origin.x = dmxScreen->rootX;
  309. pWindow->origin.y = dmxScreen->rootY;
  310. }
  311. }
  312. else {
  313. dmxGetDefaultWindowAttributes(pWindow,
  314. &pWinPriv->cmap, &pWinPriv->visual);
  315. if (dmxLazyWindowCreation) {
  316. /* Save parent's visual for use later */
  317. if (pWinPriv->visual == CopyFromParent)
  318. pWinPriv->visual =
  319. dmxLookupVisualFromID(pScreen,
  320. wVisual(pWindow->parent));
  321. }
  322. else {
  323. pWinPriv->window = dmxCreateNonRootWindow(pWindow);
  324. }
  325. }
  326. dmxSync(dmxScreen, False);
  327. }
  328. DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
  329. return ret;
  330. }
  331. /** Destroy \a pWindow on the back-end server. */
  332. Bool
  333. dmxBEDestroyWindow(WindowPtr pWindow)
  334. {
  335. ScreenPtr pScreen = pWindow->drawable.pScreen;
  336. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  337. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  338. if (pWinPriv->window) {
  339. XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window);
  340. pWinPriv->window = (Window) 0;
  341. return TRUE;
  342. }
  343. return FALSE;
  344. }
  345. /** Destroy \a pWindow on the back-end server. If any RENDER pictures
  346. were created, destroy them as well. */
  347. Bool
  348. dmxDestroyWindow(WindowPtr pWindow)
  349. {
  350. ScreenPtr pScreen = pWindow->drawable.pScreen;
  351. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  352. Bool ret = TRUE;
  353. Bool needSync = FALSE;
  354. #ifdef GLXEXT
  355. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  356. #endif
  357. DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
  358. /* Destroy any picture list associated with this window */
  359. needSync |= dmxDestroyPictureList(pWindow);
  360. /* Destroy window on back-end server */
  361. needSync |= dmxBEDestroyWindow(pWindow);
  362. if (needSync)
  363. dmxSync(dmxScreen, FALSE);
  364. #ifdef GLXEXT
  365. if (pWinPriv->swapGroup && pWinPriv->windowDestroyed)
  366. pWinPriv->windowDestroyed(pWindow);
  367. #endif
  368. if (pScreen->DestroyWindow)
  369. ret = pScreen->DestroyWindow(pWindow);
  370. DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
  371. return ret;
  372. }
  373. /** Change the position of \a pWindow to be \a x, \a y. */
  374. Bool
  375. dmxPositionWindow(WindowPtr pWindow, int x, int y)
  376. {
  377. ScreenPtr pScreen = pWindow->drawable.pScreen;
  378. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  379. Bool ret = TRUE;
  380. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  381. unsigned int m;
  382. XWindowChanges c;
  383. DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
  384. #if 0
  385. if (pScreen->PositionWindow)
  386. ret = pScreen->PositionWindow(pWindow, x, y);
  387. #endif
  388. /* Determine if the window is completely off the visible portion of
  389. the screen */
  390. pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
  391. /* If the window is now on-screen and it is mapped and it has not
  392. been created yet, create it and map it */
  393. if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
  394. dmxCreateAndRealizeWindow(pWindow, TRUE);
  395. }
  396. else if (pWinPriv->window) {
  397. /* Position window on back-end server */
  398. m = CWX | CWY | CWWidth | CWHeight;
  399. c.x = pWindow->origin.x - wBorderWidth(pWindow);
  400. c.y = pWindow->origin.y - wBorderWidth(pWindow);
  401. c.width = pWindow->drawable.width;
  402. c.height = pWindow->drawable.height;
  403. if (pWindow->drawable.class != InputOnly) {
  404. m |= CWBorderWidth;
  405. c.border_width = pWindow->borderWidth;
  406. }
  407. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  408. dmxSync(dmxScreen, False);
  409. }
  410. DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
  411. return ret;
  412. }
  413. static void
  414. dmxDoChangeWindowAttributes(WindowPtr pWindow,
  415. unsigned long *mask, XSetWindowAttributes * attribs)
  416. {
  417. dmxPixPrivPtr pPixPriv;
  418. if (*mask & CWBackPixmap) {
  419. switch (pWindow->backgroundState) {
  420. case None:
  421. attribs->background_pixmap = None;
  422. break;
  423. case ParentRelative:
  424. attribs->background_pixmap = ParentRelative;
  425. break;
  426. case BackgroundPixmap:
  427. pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap);
  428. attribs->background_pixmap = pPixPriv->pixmap;
  429. break;
  430. case BackgroundPixel:
  431. *mask &= ~CWBackPixmap;
  432. break;
  433. }
  434. }
  435. if (*mask & CWBackPixel) {
  436. if (pWindow->backgroundState == BackgroundPixel)
  437. attribs->background_pixel = pWindow->background.pixel;
  438. else
  439. *mask &= ~CWBackPixel;
  440. }
  441. if (*mask & CWBorderPixmap) {
  442. if (pWindow->borderIsPixel)
  443. *mask &= ~CWBorderPixmap;
  444. else {
  445. pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->border.pixmap);
  446. attribs->border_pixmap = pPixPriv->pixmap;
  447. }
  448. }
  449. if (*mask & CWBorderPixel) {
  450. if (pWindow->borderIsPixel)
  451. attribs->border_pixel = pWindow->border.pixel;
  452. else
  453. *mask &= ~CWBorderPixel;
  454. }
  455. if (*mask & CWBitGravity)
  456. attribs->bit_gravity = pWindow->bitGravity;
  457. if (*mask & CWWinGravity)
  458. *mask &= ~CWWinGravity; /* Handled by dix */
  459. if (*mask & CWBackingStore)
  460. *mask &= ~CWBackingStore; /* Backing store not supported */
  461. if (*mask & CWBackingPlanes)
  462. *mask &= ~CWBackingPlanes; /* Backing store not supported */
  463. if (*mask & CWBackingPixel)
  464. *mask &= ~CWBackingPixel; /* Backing store not supported */
  465. if (*mask & CWOverrideRedirect)
  466. attribs->override_redirect = pWindow->overrideRedirect;
  467. if (*mask & CWSaveUnder)
  468. *mask &= ~CWSaveUnder; /* Save unders not supported */
  469. if (*mask & CWEventMask)
  470. *mask &= ~CWEventMask; /* Events are handled by dix */
  471. if (*mask & CWDontPropagate)
  472. *mask &= ~CWDontPropagate; /* Events are handled by dix */
  473. if (*mask & CWColormap) {
  474. ColormapPtr pCmap;
  475. dmxColormapPrivPtr pCmapPriv;
  476. dixLookupResourceByType((void **) &pCmap, wColormap(pWindow),
  477. RT_COLORMAP, NullClient, DixUnknownAccess);
  478. pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
  479. attribs->colormap = pCmapPriv->cmap;
  480. }
  481. if (*mask & CWCursor)
  482. *mask &= ~CWCursor; /* Handled by the cursor code */
  483. }
  484. /** Change the window attributes of \a pWindow. */
  485. Bool
  486. dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
  487. {
  488. ScreenPtr pScreen = pWindow->drawable.pScreen;
  489. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  490. Bool ret = TRUE;
  491. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  492. XSetWindowAttributes attribs;
  493. DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
  494. #if 0
  495. if (pScreen->ChangeWindowAttributes)
  496. ret = pScreen->ChangeWindowAttributes(pWindow, mask);
  497. #endif
  498. /* Change window attribs on back-end server */
  499. dmxDoChangeWindowAttributes(pWindow, &mask, &attribs);
  500. /* Save mask for lazy window creation optimization */
  501. pWinPriv->attribMask |= mask;
  502. if (mask && pWinPriv->window) {
  503. XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window,
  504. mask, &attribs);
  505. dmxSync(dmxScreen, False);
  506. }
  507. DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
  508. pScreen);
  509. return ret;
  510. }
  511. /** Realize \a pWindow on the back-end server. If the lazy window
  512. * creation optimization is enabled, the window is only realized when
  513. * it at least partially overlaps the screen. */
  514. Bool
  515. dmxRealizeWindow(WindowPtr pWindow)
  516. {
  517. ScreenPtr pScreen = pWindow->drawable.pScreen;
  518. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  519. Bool ret = TRUE;
  520. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  521. DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
  522. #if 0
  523. if (pScreen->RealizeWindow)
  524. ret = pScreen->RealizeWindow(pWindow);
  525. #endif
  526. /* Determine if the window is completely off the visible portion of
  527. the screen */
  528. pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
  529. /* If the window hasn't been created and it's not offscreen, then
  530. create it */
  531. if (!pWinPriv->window && !pWinPriv->offscreen) {
  532. dmxCreateAndRealizeWindow(pWindow, FALSE);
  533. }
  534. if (pWinPriv->window) {
  535. /* Realize window on back-end server */
  536. XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
  537. dmxSync(dmxScreen, False);
  538. }
  539. /* Let the other functions know that the window is now mapped */
  540. pWinPriv->mapped = TRUE;
  541. DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
  542. dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow);
  543. return ret;
  544. }
  545. /** Unrealize \a pWindow on the back-end server. */
  546. Bool
  547. dmxUnrealizeWindow(WindowPtr pWindow)
  548. {
  549. ScreenPtr pScreen = pWindow->drawable.pScreen;
  550. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  551. Bool ret = TRUE;
  552. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  553. DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
  554. #if 0
  555. if (pScreen->UnrealizeWindow)
  556. ret = pScreen->UnrealizeWindow(pWindow);
  557. #endif
  558. if (pWinPriv->window) {
  559. /* Unrealize window on back-end server */
  560. XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
  561. dmxSync(dmxScreen, False);
  562. }
  563. /* When unrealized (i.e., unmapped), the window is always considered
  564. off of the visible portion of the screen */
  565. pWinPriv->offscreen = TRUE;
  566. pWinPriv->mapped = FALSE;
  567. #ifdef GLXEXT
  568. if (pWinPriv->swapGroup && pWinPriv->windowUnmapped)
  569. pWinPriv->windowUnmapped(pWindow);
  570. #endif
  571. DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
  572. dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow);
  573. return ret;
  574. }
  575. static void
  576. dmxDoRestackWindow(WindowPtr pWindow)
  577. {
  578. ScreenPtr pScreen = pWindow->drawable.pScreen;
  579. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  580. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  581. WindowPtr pNextSib = pWindow->nextSib;
  582. unsigned int m;
  583. XWindowChanges c;
  584. if (pNextSib == NullWindow) {
  585. /* Window is at the bottom of the stack */
  586. m = CWStackMode;
  587. c.sibling = (Window) 0;
  588. c.stack_mode = Below;
  589. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  590. }
  591. else {
  592. /* Window is not at the bottom of the stack */
  593. dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
  594. /* Handle case where siblings have not yet been created due to
  595. lazy window creation optimization by first finding the next
  596. sibling in the sibling list that has been created (if any)
  597. and then putting the current window just above that sibling,
  598. and if no next siblings have been created yet, then put it at
  599. the bottom of the stack (since it might have a previous
  600. sibling that should be above it). */
  601. while (!pNextSibPriv->window) {
  602. pNextSib = pNextSib->nextSib;
  603. if (pNextSib == NullWindow) {
  604. /* Window is at the bottom of the stack */
  605. m = CWStackMode;
  606. c.sibling = (Window) 0;
  607. c.stack_mode = Below;
  608. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  609. return;
  610. }
  611. pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
  612. }
  613. m = CWStackMode | CWSibling;
  614. c.sibling = pNextSibPriv->window;
  615. c.stack_mode = Above;
  616. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  617. }
  618. }
  619. /** Handle window restacking. The actual restacking occurs in
  620. * #dmxDoRestackWindow(). */
  621. void
  622. dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib)
  623. {
  624. ScreenPtr pScreen = pWindow->drawable.pScreen;
  625. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  626. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  627. DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
  628. #if 0
  629. if (pScreen->RestackWindow)
  630. pScreen->RestackWindow(pWindow, pOldNextSib);
  631. #endif
  632. if (pOldNextSib != pWindow->nextSib) {
  633. /* Track restacking for lazy window creation optimization */
  634. pWinPriv->restacked = TRUE;
  635. /* Restack window on back-end server */
  636. if (pWinPriv->window) {
  637. dmxDoRestackWindow(pWindow);
  638. dmxSync(dmxScreen, False);
  639. }
  640. }
  641. DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
  642. dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow);
  643. }
  644. static Bool
  645. dmxWindowExposurePredicate(Display * dpy, XEvent * ev, XPointer ptr)
  646. {
  647. return (ev->type == Expose && ev->xexpose.window == *(Window *) ptr);
  648. }
  649. /** Handle exposures on \a pWindow. Since window exposures are handled
  650. * in DMX, the events that are generated by the back-end server are
  651. * redundant, so we eat them here. */
  652. void
  653. dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn, RegionPtr other_exposed)
  654. {
  655. ScreenPtr pScreen = pWindow->drawable.pScreen;
  656. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  657. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  658. XEvent ev;
  659. DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
  660. dmxSync(dmxScreen, False);
  661. if (pWinPriv->window) {
  662. while (XCheckIfEvent(dmxScreen->beDisplay, &ev,
  663. dmxWindowExposurePredicate,
  664. (XPointer) &pWinPriv->window)) {
  665. /* Handle expose events -- this should not be necessary
  666. since the base window in which the root window was
  667. created is guaranteed to be on top (override_redirect),
  668. so we should just swallow these events. If for some
  669. reason the window is not on top, then we'd need to
  670. collect these events and send them to the client later
  671. (e.g., during the block handler as Xnest does). */
  672. }
  673. }
  674. #if 1
  675. if (pScreen->WindowExposures)
  676. pScreen->WindowExposures(pWindow, prgn, other_exposed);
  677. #endif
  678. DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
  679. }
  680. /** Move \a pWindow on the back-end server. Determine whether or not it
  681. * is on or offscreen, and realize it if it is newly on screen and the
  682. * lazy window creation optimization is enabled. */
  683. void
  684. dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
  685. {
  686. ScreenPtr pScreen = pWindow->drawable.pScreen;
  687. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  688. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  689. unsigned int m;
  690. XWindowChanges c;
  691. DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
  692. #if 0
  693. if (pScreen->CopyWindow)
  694. pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
  695. #endif
  696. /* Determine if the window is completely off the visible portion of
  697. the screen */
  698. pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
  699. /* If the window is now on-screen and it is mapped and it has not
  700. been created yet, create it and map it */
  701. if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
  702. dmxCreateAndRealizeWindow(pWindow, TRUE);
  703. }
  704. else if (pWinPriv->window) {
  705. /* Move window on back-end server */
  706. m = CWX | CWY | CWWidth | CWHeight;
  707. c.x = pWindow->origin.x - wBorderWidth(pWindow);
  708. c.y = pWindow->origin.y - wBorderWidth(pWindow);
  709. c.width = pWindow->drawable.width;
  710. c.height = pWindow->drawable.height;
  711. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  712. dmxSync(dmxScreen, False);
  713. }
  714. DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
  715. dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow);
  716. }
  717. /** Resize \a pWindow on the back-end server. Determine whether or not
  718. * it is on or offscreen, and realize it if it is newly on screen and
  719. * the lazy window creation optimization is enabled. */
  720. void
  721. dmxResizeWindow(WindowPtr pWindow, int x, int y,
  722. unsigned int w, unsigned int h, WindowPtr pSib)
  723. {
  724. ScreenPtr pScreen = pWindow->drawable.pScreen;
  725. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  726. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  727. dmxWinPrivPtr pSibPriv;
  728. unsigned int m;
  729. XWindowChanges c;
  730. if (pSib)
  731. pSibPriv = DMX_GET_WINDOW_PRIV(pSib);
  732. DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
  733. #if 1
  734. if (pScreen->ResizeWindow)
  735. pScreen->ResizeWindow(pWindow, x, y, w, h, pSib);
  736. #endif
  737. /* Determine if the window is completely off the visible portion of
  738. the screen */
  739. pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
  740. /* If the window is now on-screen and it is mapped and it has not
  741. been created yet, create it and map it */
  742. if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
  743. dmxCreateAndRealizeWindow(pWindow, TRUE);
  744. }
  745. else if (pWinPriv->window) {
  746. /* Handle resizing on back-end server */
  747. m = CWX | CWY | CWWidth | CWHeight;
  748. c.x = pWindow->origin.x - wBorderWidth(pWindow);
  749. c.y = pWindow->origin.y - wBorderWidth(pWindow);
  750. c.width = pWindow->drawable.width;
  751. c.height = pWindow->drawable.height;
  752. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  753. dmxSync(dmxScreen, False);
  754. }
  755. DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
  756. dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow);
  757. }
  758. /** Reparent \a pWindow on the back-end server. */
  759. void
  760. dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
  761. {
  762. ScreenPtr pScreen = pWindow->drawable.pScreen;
  763. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  764. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  765. dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
  766. DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
  767. #if 0
  768. if (pScreen->ReparentWindow)
  769. pScreen->ReparentWindow(pWindow, pPriorParent);
  770. #endif
  771. if (pWinPriv->window) {
  772. if (!pParentPriv->window) {
  773. dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
  774. }
  775. /* Handle reparenting on back-end server */
  776. XReparentWindow(dmxScreen->beDisplay, pWinPriv->window,
  777. pParentPriv->window,
  778. pWindow->origin.x - wBorderWidth(pWindow),
  779. pWindow->origin.x - wBorderWidth(pWindow));
  780. dmxSync(dmxScreen, False);
  781. }
  782. DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
  783. dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow);
  784. }
  785. /** Change border width for \a pWindow to \a width pixels. */
  786. void
  787. dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width)
  788. {
  789. ScreenPtr pScreen = pWindow->drawable.pScreen;
  790. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  791. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  792. unsigned int m;
  793. XWindowChanges c;
  794. DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
  795. #if 1
  796. if (pScreen->ChangeBorderWidth)
  797. pScreen->ChangeBorderWidth(pWindow, width);
  798. #endif
  799. /* NOTE: Do we need to check for on/off screen here? */
  800. if (pWinPriv->window) {
  801. /* Handle border width change on back-end server */
  802. m = CWBorderWidth;
  803. c.border_width = width;
  804. XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
  805. dmxSync(dmxScreen, False);
  806. }
  807. DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
  808. }
  809. static void
  810. dmxDoSetShape(WindowPtr pWindow)
  811. {
  812. ScreenPtr pScreen = pWindow->drawable.pScreen;
  813. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  814. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  815. int nBox;
  816. BoxPtr pBox;
  817. int nRect;
  818. XRectangle *pRect;
  819. XRectangle *pRectFirst;
  820. /* First, set the bounding shape */
  821. if (wBoundingShape(pWindow)) {
  822. pBox = RegionRects(wBoundingShape(pWindow));
  823. nRect = nBox = RegionNumRects(wBoundingShape(pWindow));
  824. pRectFirst = pRect = malloc(nRect * sizeof(*pRect));
  825. while (nBox--) {
  826. pRect->x = pBox->x1;
  827. pRect->y = pBox->y1;
  828. pRect->width = pBox->x2 - pBox->x1;
  829. pRect->height = pBox->y2 - pBox->y1;
  830. pBox++;
  831. pRect++;
  832. }
  833. XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
  834. ShapeBounding, 0, 0,
  835. pRectFirst, nRect, ShapeSet, YXBanded);
  836. free(pRectFirst);
  837. }
  838. else {
  839. XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
  840. ShapeBounding, 0, 0, None, ShapeSet);
  841. }
  842. /* Next, set the clip shape */
  843. if (wClipShape(pWindow)) {
  844. pBox = RegionRects(wClipShape(pWindow));
  845. nRect = nBox = RegionNumRects(wClipShape(pWindow));
  846. pRectFirst = pRect = malloc(nRect * sizeof(*pRect));
  847. while (nBox--) {
  848. pRect->x = pBox->x1;
  849. pRect->y = pBox->y1;
  850. pRect->width = pBox->x2 - pBox->x1;
  851. pRect->height = pBox->y2 - pBox->y1;
  852. pBox++;
  853. pRect++;
  854. }
  855. XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
  856. ShapeClip, 0, 0,
  857. pRectFirst, nRect, ShapeSet, YXBanded);
  858. free(pRectFirst);
  859. }
  860. else {
  861. XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
  862. ShapeClip, 0, 0, None, ShapeSet);
  863. }
  864. if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) {
  865. ErrorF("Input selected for window %x on Screen %d\n",
  866. (unsigned int) pWinPriv->window, pScreen->myNum);
  867. }
  868. }
  869. /** Set shape of \a pWindow on the back-end server. */
  870. void
  871. dmxSetShape(WindowPtr pWindow, int kind)
  872. {
  873. ScreenPtr pScreen = pWindow->drawable.pScreen;
  874. DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
  875. dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
  876. DMX_UNWRAP(SetShape, dmxScreen, pScreen);
  877. #if 1
  878. if (pScreen->SetShape)
  879. pScreen->SetShape(pWindow, kind);
  880. #endif
  881. if (pWinPriv->window) {
  882. /* Handle setting the current shape on the back-end server */
  883. dmxDoSetShape(pWindow);
  884. dmxSync(dmxScreen, False);
  885. }
  886. else {
  887. pWinPriv->isShaped = TRUE;
  888. }
  889. DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
  890. }