home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume15 / olvwm-3.0 / part02 < prev    next >
Text File  |  1992-02-03  |  56KB  |  1,913 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!usc!elroy.jpl.nasa.gov!ames!pasteur!nntp
  3. From: scott.oaks@East.Sun.COM (Scott Oaks)
  4. Subject: v15i148: OpenLook Virtual Window Mgr (3.0), Part02/21
  5. Message-ID: <1992Feb4.135406.6724@pasteur.Berkeley.EDU>
  6. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  7. Nntp-Posting-Host: postgres.berkeley.edu
  8. Organization: University of California, at Berkeley
  9. References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
  10. Date: Tue, 4 Feb 1992 13:54:06 GMT
  11. Approved: dcmartin@msi.com
  12.  
  13. Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
  14. Posting-number: Volume 15, Issue 148
  15. Archive-name: olvwm-3.0/part02
  16.  
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  21. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  22. # If this archive is complete, you will see the following message at the end:
  23. #        "End of archive 2 (of 21)."
  24. # Contents:  patchlevel.h virtual.c
  25. # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:41 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  29. else
  30. echo shar: Extracting \"'patchlevel.h'\" \(24 characters\)
  31. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  32. X#define PATCHLEVELv3 0    
  33. END_OF_FILE
  34. if test 24 -ne `wc -c <'patchlevel.h'`; then
  35.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  36. fi
  37. # end of 'patchlevel.h'
  38. fi
  39. if test -f 'virtual.c' -a "${1}" != "-c" ; then 
  40.   echo shar: Will not clobber existing file \"'virtual.c'\"
  41. else
  42. echo shar: Extracting \"'virtual.c'\" \(51849 characters\)
  43. sed "s/^X//" >'virtual.c' <<'END_OF_FILE'
  44. X/*
  45. X * (c) Copyright 1991 Scott Oaks.  See LEGAL_NOTICE file for terms of the
  46. X * license
  47. X */
  48. X
  49. X#include <stdio.h>
  50. X#include <string.h>
  51. X#include <dirent.h>
  52. X#include <X11/Xos.h>
  53. X#include <X11/Xlib.h>
  54. X#include <X11/Xutil.h>
  55. X#include <X11/keysym.h>
  56. X#include <X11/keysymdef.h>
  57. X#include <X11/Xatom.h>
  58. X
  59. X#include "i18n.h"
  60. X#include "ollocale.h"
  61. X#include "mem.h"
  62. X#include "olwm.h"
  63. X#include "st.h"
  64. X#include "globals.h"
  65. X#include "win.h"
  66. X#include "menu.h"
  67. X#include "math.h"
  68. X#include "virtual.h"
  69. X#include "patchlevel.h"
  70. X
  71. X#include "vdm.icon"
  72. X#include "vdm.mask"
  73. X
  74. X/* Class Function Vector; a virtual pane is the VDM window in which all
  75. X * the little virtual windows appear (and to which said windows are
  76. X * parented)
  77. X */
  78. Xstatic ClassVirtualPane    classVirtualPane;
  79. X
  80. X/*
  81. X * Last select time in the VDM.  This is technically different for each
  82. X * VDM, but who can click in a VDM, move between screens, and then click
  83. X * again?
  84. X */
  85. Xstatic int    lastSelectTime;
  86. X
  87. Xextern List    *ScreenInfoList;
  88. X
  89. Xextern Pixmap    VirtualGetPixmap();
  90. X
  91. Xextern Button    *MakeUpLeftButton(),*MakeLeftButton(),*MakeDownLeftButton(),
  92. X        *MakeUpButton(),*MakeHomeButton(),*MakeDownButton(),
  93. X        *MakeUpRightButton(),*MakeRightButton(),*MakeDownRightButton();
  94. X
  95. X/*
  96. X * Semantic action associated with each of the buttons above.  These must
  97. X * be in the same order as the button array; it would be better if the Button
  98. X * structure had an opaque entry for this purpose.
  99. X */
  100. X
  101. Xstatic SemanticAction    vdmButtonActions[] = {
  102. X    ACTION_UPLEFT,
  103. X    ACTION_LEFT,
  104. X    ACTION_DOWNLEFT,
  105. X    ACTION_UP,
  106. X    ACTION_HOME,
  107. X    ACTION_DOWN,
  108. X    ACTION_UPRIGHT,
  109. X    ACTION_RIGHT,
  110. X    ACTION_DOWNRIGHT,
  111. X};
  112. X
  113. Xstatic char pixdata[] = { 0xaa, 0x55 };
  114. X
  115. X#define VDMSelectMask (ButtonPressMask | ButtonReleaseMask | \
  116. X               ButtonMotionMask | ExposureMask )
  117. X
  118. X/*
  119. X * ==========================================================================
  120. X *
  121. X * VDM Utility/Drawing/Moving Functions
  122. X *
  123. X */
  124. X
  125. X/*
  126. X * Draw the dotted lines on the VDM background
  127. X */
  128. Xstatic void
  129. XdrawVDMGrid(dpy, vdm)
  130. X    Display        *dpy;
  131. X    VirtualDesktop    *vdm;
  132. X
  133. X{
  134. Xint        i;
  135. XXPoint        pts[5];
  136. Xint        dh = DisplayHeight(dpy, vdm->client->screen);
  137. Xint        dw = DisplayWidth(dpy, vdm->client->screen);
  138. XScreenInfo    *scrInfo = vdm->client->scrInfo;
  139. X
  140. X    XClearArea(dpy, PANEWINOFCLIENT(vdm->client), 0, 0, 0, 0, 0);
  141. X    XSetForeground(dpy, scrInfo->gc[VDM_GC],
  142. X           scrInfo->colorInfo.virtualGridColor);
  143. X    if (vdm->resources->grid == GridVisible) {
  144. X    XSetLineAttributes(dpy, scrInfo->gc[VDM_GC], 0, LineOnOffDash,
  145. X               CapNotLast, JoinMiter);
  146. X    pts[0].y = 0;
  147. X    pts[1].y = vdm->height;
  148. X    for (i = dw; i < vdm->absoluteWidth; i += dw) {
  149. X        pts[0].x = pts[1].x = i / vdm->resources->scale;
  150. X        XDrawLines(dpy, PANEWINOFCLIENT(vdm->client), scrInfo->gc[VDM_GC],
  151. X            pts, 2, CoordModeOrigin);
  152. X    }
  153. X    pts[0].x = 0;
  154. X    pts[1].x = vdm->width;
  155. X    for (i = dh; i < vdm->absoluteHeight; i+= dh) {
  156. X        pts[0].y = pts[1].y = i / vdm->resources->scale;
  157. X        XDrawLines(dpy, PANEWINOFCLIENT(vdm->client), scrInfo->gc[VDM_GC],
  158. X            pts, 2, CoordModeOrigin);
  159. X    }
  160. X    XSetLineAttributes(dpy, scrInfo->gc[VDM_GC], 0,
  161. X               LineSolid, CapNotLast, JoinMiter);
  162. X    }
  163. X    pts[0].x = pts[4].x = -vdm->offsetX / vdm->resources->scale;
  164. X    pts[0].y = pts[4].y = -vdm->offsetY / vdm->resources->scale;
  165. X    pts[1].x = (dw - vdm->offsetX) / vdm->resources->scale;
  166. X    pts[1].y = pts[0].y;
  167. X    pts[2].x = pts[1].x;
  168. X    pts[2].y = (dh - vdm->offsetY) / vdm->resources->scale;
  169. X    pts[3].x = pts[0].x;
  170. X    pts[3].y = pts[2].y;
  171. X    XDrawLines(dpy, PANEWINOFCLIENT(vdm->client), scrInfo->gc[VDM_GC],
  172. X        pts, 5, CoordModeOrigin);
  173. X    XSetForeground(dpy, scrInfo->gc[VDM_GC], scrInfo->colorInfo.virtualFontColor);
  174. X}
  175. X
  176. X/*
  177. X *  Function for re-placing (not replacing!) all windows when the view into
  178. X *  the desktop is changed
  179. X */
  180. Xtypedef struct _replacestickyinfo {
  181. X    struct deltas    *deltas;
  182. X    int            screen;
  183. X} replaceStickyInfo;
  184. X
  185. Xstatic void *
  186. XreplaceSticky(cli, c)
  187. X    Client        *cli;
  188. X    replaceStickyInfo    *c;
  189. X
  190. X{
  191. XWinGenericFrame    *win;
  192. X
  193. X    if (cli->screen != c->screen)
  194. X    return NULL;
  195. X    if (cli && !cli->sticky) {
  196. X    win = (WinGenericFrame *) cli->framewin;
  197. X    if (win)
  198. X        GFrameSetConfig(win, (int) (win->core.x - c->deltas->delta_x),
  199. X                (int) (win->core.y - c->deltas->delta_y),
  200. X                win->core.width, win->core.height);
  201. X    win = (WinGenericFrame *) cli->iconwin;
  202. X    if (win)
  203. X        GFrameSetConfig(win, (int) (win->core.x - c->deltas->delta_x),
  204. X                (int) (win->core.y - c->deltas->delta_y),
  205. X                win->core.width, win->core.height);
  206. X    }
  207. X    else if (cli) {
  208. X    /*
  209. X     * client is sticky; its real window stays where it is but its
  210. X     * virtual window must move
  211. X     */
  212. X    if (cli->framewin)
  213. X        XMoveWindow(cli->dpy, cli->framewin->core.virtual,
  214. X            (cli->framewin->core.x) / cli->scrInfo->vdm->resources->scale +
  215. X                cli->scrInfo->vdm->screenX,
  216. X            (cli->framewin->core.y) / cli->scrInfo->vdm->resources->scale +
  217. X                cli->scrInfo->vdm->screenY);
  218. X    if (cli->iconwin)
  219. X        XMoveWindow(cli->dpy, cli->iconwin->core.virtual,
  220. X            (cli->iconwin->core.x) / cli->scrInfo->vdm->resources->scale +
  221. X                cli->scrInfo->vdm->screenX,
  222. X            (cli->iconwin->core.y) / cli->scrInfo->vdm->resources->scale +
  223. X                cli->scrInfo->vdm->screenY);
  224. X    }
  225. X    return NULL;
  226. X}
  227. X
  228. Xstatic void
  229. XmoveDesktop(dpy, deltas, vdm)
  230. X    Display        *dpy;
  231. X    struct deltas    *deltas;
  232. X    VirtualDesktop    *vdm;
  233. X{
  234. Xextern List    *ActiveClientList;
  235. XreplaceStickyInfo    info;
  236. X
  237. X    vdm->offsetX -= deltas->delta_x;
  238. X    vdm->offsetY -= deltas->delta_y;
  239. X    vdm->screenX = -vdm->offsetX / vdm->resources->scale;
  240. X    vdm->screenY = -vdm->offsetY / vdm->resources->scale;
  241. X    info.screen = vdm->client->screen;
  242. X    info.deltas = deltas;
  243. X    ListApply(ActiveClientList, replaceSticky, &info);
  244. X    drawVDMGrid(dpy, vdm);
  245. X}
  246. X
  247. X/*
  248. X * Make sure the given deltas don't move off the screen
  249. X */
  250. Xstatic void
  251. XconstrainDeltas(dpy, vdm, deltas)
  252. X    Display        *dpy;
  253. X    VirtualDesktop    *vdm;
  254. X    struct deltas    *deltas;
  255. X{
  256. Xint    dw = DisplayWidth(dpy, vdm->client->screen);
  257. Xint    dh = DisplayHeight(dpy, vdm->client->screen);
  258. X
  259. X    if (vdm->offsetX - deltas->delta_x < dw - vdm->absoluteWidth)
  260. X    deltas->delta_x = vdm->offsetX + vdm->absoluteWidth - dw;
  261. X    else if (vdm->offsetX - deltas->delta_x > 0)
  262. X    deltas->delta_x = vdm->offsetX;
  263. X
  264. X    if (vdm->offsetY - deltas->delta_y < dh - vdm->absoluteHeight)
  265. X    deltas->delta_y = vdm->offsetY + vdm->absoluteHeight - dh;
  266. X    else if (vdm->offsetY - deltas->delta_y > 0)
  267. X    deltas->delta_y = vdm->offsetY;
  268. X}
  269. Xstatic Bool
  270. XvdmPerformAction(dpy, vdm, a)
  271. X    Display        *dpy;
  272. X    VirtualDesktop    *vdm;
  273. X    SemanticAction    a;
  274. X
  275. X{
  276. Xstruct deltas    deltas;
  277. Xint    dh = DisplayHeight(dpy, vdm->client->screen);
  278. Xint    dw = DisplayWidth(dpy, vdm->client->screen);
  279. X
  280. X    deltas.delta_x = deltas.delta_y = 0;
  281. X    switch(a) {
  282. X    case ACTION_UP:
  283. X        deltas.delta_y = -dh;
  284. X        break;
  285. X    case ACTION_JUMP_UP:
  286. X        deltas.delta_y = -dh * 20;
  287. X        break;
  288. X    case ACTION_HALF_UP:
  289. X        deltas.delta_y = -dh * .5;
  290. X        break;
  291. X    case ACTION_DOWN:
  292. X        deltas.delta_y = dh;
  293. X        break;
  294. X    case ACTION_JUMP_DOWN:
  295. X        deltas.delta_y = dh * 20;
  296. X        break;
  297. X    case ACTION_HALF_DOWN:
  298. X        deltas.delta_y = dh * .5;
  299. X        break;
  300. X    case ACTION_LEFT:
  301. X        deltas.delta_x = -dw;
  302. X        break;
  303. X    case ACTION_JUMP_LEFT:
  304. X        deltas.delta_x = -dw * 20;
  305. X        break;
  306. X    case ACTION_HALF_LEFT:
  307. X        deltas.delta_x = -dw * .5;
  308. X        break;
  309. X    case ACTION_RIGHT:
  310. X        deltas.delta_x = dw;
  311. X        break;
  312. X    case ACTION_JUMP_RIGHT:
  313. X        deltas.delta_x = dw * 20;
  314. X        break;
  315. X    case ACTION_HALF_RIGHT:
  316. X        deltas.delta_x = dw * .5;
  317. X        break;
  318. X    case ACTION_UPLEFT:
  319. X    case ACTION_ROW_START:
  320. X        deltas.delta_x = -dw;
  321. X        deltas.delta_y = -dh;
  322. X        break;
  323. X    case ACTION_JUMP_UPLEFT:
  324. X        deltas.delta_x = -dw * 20;
  325. X        deltas.delta_y = -dh * 20;
  326. X        break;
  327. X    case ACTION_HALF_UPLEFT:
  328. X    case ACTION_DATA_START:
  329. X        deltas.delta_x = -dw * .5;
  330. X        deltas.delta_y = -dh * .5;
  331. X        break;
  332. X    case ACTION_UPRIGHT:
  333. X        deltas.delta_x = dw;
  334. X        deltas.delta_y = -dh;
  335. X        break;
  336. X    case ACTION_JUMP_UPRIGHT:
  337. X        deltas.delta_x = dw * 20;
  338. X        deltas.delta_y = -dh * 20;
  339. X        break;
  340. X    case ACTION_HALF_UPRIGHT:
  341. X        deltas.delta_x = dw * .5;
  342. X        deltas.delta_y = -dh * .5;
  343. X        break;
  344. X    case ACTION_HOME:
  345. X        deltas.delta_x = vdm->offsetX;
  346. X        deltas.delta_y = vdm->offsetY;
  347. X        break;
  348. X    case ACTION_DOWNLEFT:
  349. X    case ACTION_ROW_END:
  350. X        deltas.delta_x = -dw;
  351. X        deltas.delta_y = dh;
  352. X        break;
  353. X    case ACTION_JUMP_DOWNLEFT:
  354. X        deltas.delta_x = -dw * 20;
  355. X        deltas.delta_y = dh * 20;
  356. X        break;
  357. X    case ACTION_HALF_DOWNLEFT:
  358. X    case ACTION_DATA_END:
  359. X        deltas.delta_x = -dw * .5;
  360. X        deltas.delta_y = dh * .5;
  361. X        break;
  362. X    case ACTION_DOWNRIGHT:
  363. X        deltas.delta_x = dw;
  364. X        deltas.delta_y = dh;
  365. X        break;
  366. X    case ACTION_JUMP_DOWNRIGHT:
  367. X        deltas.delta_x = dw * 20;
  368. X        deltas.delta_y = dh * 20;
  369. X        break;
  370. X    case ACTION_HALF_DOWNRIGHT:
  371. X        deltas.delta_x = dw * .5;
  372. X        deltas.delta_y = dh * .5;
  373. X        break;
  374. X    case ACTION_GOTO_1:
  375. X    case ACTION_GOTO_2:
  376. X    case ACTION_GOTO_3:
  377. X    case ACTION_GOTO_4:
  378. X    case ACTION_GOTO_5:
  379. X    case ACTION_GOTO_6:
  380. X    case ACTION_GOTO_7:
  381. X    case ACTION_GOTO_8:
  382. X    case ACTION_GOTO_9:
  383. X    case ACTION_GOTO_10:
  384. X        deltas.delta_x = vdm->offsetX +
  385. X                ((a - ACTION_GOTO_1) % vdm->columns) * dw;
  386. X        deltas.delta_y = vdm->offsetY +
  387. X                ((a - ACTION_GOTO_1) / vdm->columns) * dh;
  388. X        break;
  389. X    default:
  390. X        return False;
  391. X    }
  392. X    constrainDeltas(dpy, vdm, &deltas);
  393. X
  394. X    if (fabs(deltas.delta_x) < 0.1 && fabs(deltas.delta_y) < 0.1)
  395. X    return False;
  396. X    moveDesktop(dpy, &deltas, vdm);
  397. X    return True;
  398. X}
  399. X
  400. X/*
  401. X * Given root and logical coordinates relative to the VDM, turn them into
  402. X * absolute screen coordinates
  403. X */
  404. Xstatic void
  405. XtranslateVirtualCoords(vdm, root_x, root_y, x, y)
  406. X    VirtualDesktop    *vdm;
  407. X    int            *root_x, *root_y, *x, *y;
  408. X
  409. X{
  410. Xint     tx, ty, tw, th, bw, d;
  411. XWindow  root;
  412. X
  413. X    if (x)
  414. X    *x *= vdm->resources->scale;
  415. X    if (y)
  416. X    *y *= vdm->resources->scale;
  417. X    if (!root_x || !root_y)
  418. X    return;
  419. X    XGetGeometry(vdm->client->dpy, vdm->client->framewin->core.self,
  420. X         &root, &tx, &ty, &tw, &th, &bw, &d);
  421. X    *root_x -= tx;
  422. X    *root_y -= ty;
  423. X    XGetGeometry(vdm->client->dpy,
  424. X         vdm->client->framewin->fcore.panewin->core.self,
  425. X         &root, &tx, &ty, &tw, &th, &bw, &d);
  426. X    *root_x -= tx;
  427. X    *root_y -= ty;
  428. X    *root_x *= vdm->resources->scale;
  429. X    *root_x += vdm->offsetX;
  430. X    *root_y *= vdm->resources->scale;
  431. X    *root_y += vdm->offsetY;
  432. X}
  433. X
  434. Xvoid
  435. XcalculateVirtualDesktopSize(dpy, screen, v)
  436. X    Display        *dpy;
  437. X    int            screen;
  438. X    VirtualDesktop    *v;
  439. X
  440. X{
  441. X    int    width, height;
  442. X    int    dw = DisplayWidth(dpy, screen);
  443. X    int    dh = DisplayHeight(dpy, screen);
  444. X
  445. X    sscanf(v->resources->size, "%dx%d", &width, &height);
  446. X    if (width < dw)
  447. X        v->columns = width;
  448. X    else v->columns = ceil((double) width / dw);
  449. X    if (height < dh)
  450. X    v->rows = height;
  451. X    else v->rows = ceil((double) height / dh);
  452. X
  453. X    v->absoluteWidth = v->columns * dw;
  454. X    v->absoluteHeight = v->rows * dh;
  455. X
  456. X    v->screenWidth = dw / v->resources->scale;
  457. X    v->screenHeight = dh / v->resources->scale;
  458. X    if (v->resources->grid) {
  459. X        v->width = v->columns * v->screenWidth;
  460. X        v->height = v->rows * v->screenHeight;
  461. X    }
  462. X    else {
  463. X    v->width = v->absoluteWidth / v->resources->scale;
  464. X    v->height = v->absoluteHeight / v->resources->scale;
  465. X    }
  466. X}
  467. X
  468. X/*
  469. X * Allocate a virtual desktop for the given screen.
  470. X * See virtual.h for a definition of all the fields in the returned structure.
  471. X *
  472. X * This doesn't deal with the window stuff, just with the fields.  The
  473. X * window is actually created and the colors set etc. below in MakeVDM
  474. X *
  475. X */
  476. X
  477. Xstatic VirtualDesktop *
  478. XallocVirtualDesktop(dpy, screen, rsc)
  479. X    Display        *dpy;
  480. X    int            screen;
  481. X    VirtualResources    *rsc;
  482. X
  483. X{
  484. X    VirtualDesktop    *v;
  485. X
  486. X    v = (VirtualDesktop *) MemAlloc(sizeof(VirtualDesktop));
  487. X    v->resources = rsc;
  488. X    v->offsetX = 0;
  489. X    v->offsetY = 0;
  490. X    v->screenX = 0;
  491. X    v->screenY = 0;
  492. X    calculateVirtualDesktopSize(dpy, screen, v);
  493. X    return v;
  494. X}
  495. X
  496. Xstatic void
  497. XconstrainOutline(dpy, stuff, x, y, snap)
  498. X    Display    *dpy;
  499. X    VDMstuff    *stuff;
  500. X    int        x, y, snap;
  501. X{
  502. Xint    dw = DisplayWidth(dpy, stuff->vdm->client->screen);
  503. Xint    dh = DisplayHeight(dpy, stuff->vdm->client->screen);
  504. X
  505. X    if (snap) {
  506. X    stuff->vdm->screenX = (((x * stuff->vdm->resources->scale) / dw) * dw) /
  507. X                        stuff->vdm->resources->scale;
  508. X    stuff->vdm->screenY = (((y * stuff->vdm->resources->scale) / dh) * dh) /
  509. X                        stuff->vdm->resources->scale;
  510. X    }
  511. X    else {
  512. X    stuff->vdm->screenX = x - stuff->pointerX + stuff->initX;
  513. X    stuff->vdm->screenY = y - stuff->pointerY + stuff->initY;
  514. X    }
  515. X
  516. X    if (stuff->vdm->screenX < 0)
  517. X    stuff->vdm->screenX = 0;
  518. X    else if (stuff->vdm->screenX + stuff->vdm->screenWidth >
  519. X            stuff->vdm->width + stuff->vdm->resources->scale)
  520. X    stuff->vdm->screenX = (stuff->vdm->absoluteWidth - dw) /
  521. X                    stuff->vdm->resources->scale;
  522. X
  523. X    if (stuff->vdm->screenY < 0)
  524. X    stuff->vdm->screenY = 0;
  525. X    else if (stuff->vdm->screenY + stuff->vdm->screenHeight >
  526. X            stuff->vdm->height + stuff->vdm->resources->scale)
  527. X    stuff->vdm->screenY = (stuff->vdm->absoluteHeight - dh) /
  528. X                    stuff->vdm->resources->scale;
  529. X}
  530. X
  531. X/*
  532. X * ==========================================================================
  533. X *  Interposition functions for mouse dragging
  534. X */
  535. X
  536. Xstatic
  537. XvdmMoveUpdate(ev, stuff)
  538. X    XEvent    *ev;
  539. X    VDMstuff    *stuff;
  540. X{
  541. X    XDrawRectangle(stuff->vdm->client->dpy, PANEWINOFCLIENT(stuff->vdm->client),
  542. X           stuff->gc, stuff->vdm->screenX, stuff->vdm->screenY,
  543. X           stuff->vdm->screenWidth + 1, stuff->vdm->screenHeight);
  544. X    constrainOutline(stuff->vdm->client->dpy, stuff,
  545. X             ev->xmotion.x, ev->xmotion.y,
  546. X             (stuff->vdm->resources->grid) ?
  547. X            !(ev->xbutton.state & ControlMask) :
  548. X                  (ev->xbutton.state & ControlMask));
  549. X    XDrawRectangle(stuff->vdm->client->dpy, PANEWINOFCLIENT(stuff->vdm->client),
  550. X           stuff->gc, stuff->vdm->screenX, stuff->vdm->screenY,
  551. X           stuff->vdm->screenWidth + 1, stuff->vdm->screenHeight);
  552. X    stuff->numMoves++;
  553. X}
  554. X
  555. Xstatic
  556. XvdmMoveDone(ev, stuff)
  557. X    XEvent    *ev;
  558. X    VDMstuff    *stuff;
  559. X{
  560. Xstruct deltas    deltas;
  561. Xint        dw = DisplayWidth(stuff->vdm->client->dpy,
  562. X                  stuff->vdm->client->screen);
  563. Xint        dh = DisplayHeight(stuff->vdm->client->dpy,
  564. X                   stuff->vdm->client->screen);
  565. X
  566. X    UninstallInterposer();
  567. X    XDrawRectangle(stuff->vdm->client->dpy, PANEWINOFCLIENT(stuff->vdm->client),
  568. X           stuff->gc, stuff->vdm->screenX, stuff->vdm->screenY,
  569. X           stuff->vdm->screenWidth + 1, stuff->vdm->screenHeight);
  570. X    if (ev->xbutton.time - lastSelectTime <= GRV.DoubleClickTime) {
  571. X    translateVirtualCoords(stuff->vdm,
  572. X                   &ev->xbutton.x_root, &ev->xbutton.y_root,
  573. X                   &ev->xbutton.x, &ev->xbutton.y);
  574. X    VDMMoveTo(stuff->vdm->client->dpy, stuff->vdm->client,
  575. X          ev->xbutton.x_root, ev->xbutton.y_root);
  576. X    return;
  577. X    }
  578. X    lastSelectTime = ev->xbutton.time;
  579. X    if (!stuff->numMoves)
  580. X    return;
  581. X    constrainOutline(stuff->vdm->client->dpy, stuff,
  582. X             ev->xmotion.x, ev->xmotion.y,
  583. X             (stuff->vdm->resources->grid) ?
  584. X                !(ev->xbutton.state & ControlMask) :
  585. X                 (ev->xbutton.state & ControlMask));
  586. X    drawVDMGrid(stuff->vdm->client->dpy, stuff->vdm);
  587. X    deltas.delta_x = (stuff->vdm->screenX - stuff->initX) *
  588. X        stuff->vdm->resources->scale + stuff->vdm->resources->scale;
  589. X    deltas.delta_y = (stuff->vdm->screenY - stuff->initY) *
  590. X        stuff->vdm->resources->scale + stuff->vdm->resources->scale;
  591. X    if ((stuff->vdm->resources->grid && !(ev->xbutton.state & ControlMask)) ||
  592. X    (!stuff->vdm->resources->grid && (ev->xbutton.state & ControlMask))) {
  593. X    deltas.delta_x =
  594. X        (((int) (deltas.delta_x - stuff->vdm->offsetX) / dw) * dw) +
  595. X                stuff->vdm->offsetX;
  596. X    deltas.delta_y =
  597. X        (((int) (deltas.delta_y - stuff->vdm->offsetY) / dh) * dh) +
  598. X                stuff->vdm->offsetY;
  599. X    }
  600. X    moveDesktop(stuff->vdm->client->dpy, &deltas, stuff->vdm);
  601. X}
  602. X
  603. Xstatic Bool
  604. XvdmInterposer(dpy, event, w, stuff)
  605. X    Display    *dpy;
  606. X    XEvent    *event;
  607. X    WinGeneric    *w;
  608. X    VDMstuff    *stuff;
  609. X{
  610. XXEvent        nextevent;
  611. XSemanticAction    action;
  612. X
  613. X    switch(event->type) {
  614. X    case ButtonRelease:
  615. X        if (AllButtonsUp(event)) {
  616. X        vdmMoveDone(event, stuff);
  617. X        }
  618. X        break;
  619. X    case MotionNotify:
  620. X        if (!event->xmotion.same_screen)
  621. X        break;
  622. X        if (XEventsQueued(dpy, QueuedAfterReading) > 0 &&
  623. X        XPeekEvent(dpy, &nextevent), nextevent.type == MotionNotify)
  624. X        /* Ignore this event, there's another one coming */
  625. X        break;
  626. X        vdmMoveUpdate(event, stuff);
  627. X        break;
  628. X    case Expose:
  629. X        return DISPOSE_DISPATCH;
  630. X    case KeyPress:
  631. X        action = FindKeyboardAction(dpy, event);
  632. X        if (action == ACTION_STOP) {
  633. X        event->xany.type = ButtonRelease;
  634. X        event->xbutton.time = 0;
  635. X        stuff->numMoves = 0;
  636. X        vdmMoveDone(event, stuff);
  637. X        }
  638. X        else return DISPOSE_DEFER;
  639. X        break;
  640. X    default:
  641. X        return DISPOSE_DEFER;
  642. X    }
  643. X    return DISPOSE_USED;
  644. X}
  645. X
  646. X/*
  647. X * ===========================================================================
  648. X *
  649. X * Event functions for the VDM
  650. X */
  651. Xstatic
  652. XvdmExpose(dpy, event, winInfo)
  653. X    Display    *dpy;
  654. X    XEvent    *event;
  655. X    WinGeneric    *winInfo;
  656. X{
  657. XXEvent    dummy;
  658. X
  659. X    if (event->xexpose.count)
  660. X    return;
  661. X    drawVDMGrid(dpy, winInfo->core.client->scrInfo->vdm);
  662. X    while (XCheckTypedWindowEvent(dpy, event->xany.window, Expose, &dummy))
  663. X    ;    /* empty */
  664. X}
  665. X
  666. Xstatic
  667. XvdmKeyPress(dpy, ev, winInfo)
  668. X    Display    *dpy;
  669. X    XEvent    *ev;
  670. X    WinGeneric    *winInfo;
  671. X{
  672. X    if (!KeyMoveVDM(dpy, ev))
  673. X    if (GRV.Beep == BeepAlways)
  674. X        NoFocusEventBeep(dpy, ev, winInfo);
  675. X}
  676. X
  677. Xstatic
  678. XvdmConfigure(dpy, event, winInfo)
  679. X    Display        *dpy;
  680. X    XConfigureEvent    *event;
  681. X    WinVirtual        *winInfo;
  682. X{
  683. XVirtualDesktop    *vdm;
  684. Xint        dw, dh;
  685. XBool        doit;
  686. Xstruct deltas    deltas;
  687. X
  688. X    vdm = winInfo->core.client->scrInfo->vdm;
  689. X    dw = DisplayWidth(dpy, winInfo->core.client->screen);
  690. X    dh = DisplayHeight(dpy, winInfo->core.client->screen);
  691. X    vdm->width = event->width;
  692. X    vdm->height = event->height;
  693. X    if (vdm->resources->grid) {
  694. X        vdm->absoluteHeight = (vdm->height - 3) * vdm->resources->scale;
  695. X        vdm->absoluteHeight = ((vdm->absoluteHeight - 1) / dh + 1) * dh;
  696. X        vdm->absoluteWidth = (vdm->width - 3) * vdm->resources->scale;
  697. X        vdm->absoluteWidth = ((vdm->absoluteWidth - 1) / dw + 1) * dw;
  698. X        vdm->rows = ceil((double) vdm->absoluteHeight / dh);
  699. X        vdm->columns = ceil((double) vdm->absoluteWidth / dw);
  700. X    }
  701. X    else {
  702. X        vdm->absoluteHeight = vdm->height * vdm->resources->scale;
  703. X        vdm->absoluteWidth = vdm->width * vdm->resources->scale;
  704. X        vdm->rows = ceil((double) vdm->absoluteHeight / dh);
  705. X        vdm->columns = ceil((double) vdm->absoluteWidth / dw);
  706. X    }
  707. X    doit = False;
  708. X    deltas.delta_x = deltas.delta_y = 0;
  709. X    if (vdm->screenX + vdm->screenWidth > vdm->width) {
  710. X    doit = True;
  711. X    deltas.delta_x = (vdm->width - vdm->screenWidth - vdm->screenX) *
  712. X                vdm->resources->scale;
  713. X    }
  714. X    if (vdm->screenY + vdm->screenHeight > vdm->height) {
  715. X    doit = True;
  716. X    deltas.delta_y = (vdm->height - vdm->screenHeight - vdm->screenY) *
  717. X                vdm->resources->scale;
  718. X    }
  719. X    if (doit) {
  720. X    if (deltas.delta_x < 0)
  721. X        deltas.delta_x = ((int) (deltas.delta_x - vdm->resources->scale) / dw) * dw;
  722. X    else deltas.delta_x = ((int) (deltas.delta_x + vdm->resources->scale) / dw) * dw;
  723. X    if (deltas.delta_y < 0)
  724. X        deltas.delta_y = ((int) (deltas.delta_y - vdm->resources->scale) / dh) * dh;
  725. X    else deltas.delta_y = ((int) (deltas.delta_y + vdm->resources->scale) / dh) * dh;
  726. X    moveDesktop(dpy, &deltas, vdm);
  727. X    }
  728. X}
  729. X
  730. Xstatic
  731. XvdmNewConfigure(winInfo, pxcre)
  732. X    WinVirtual            *winInfo;
  733. X    XConfigureRequestEvent    *pxcre;
  734. X{
  735. Xint    oldWidth, oldHeight, oldX, oldY;
  736. XClient    *cli = winInfo->core.client;
  737. XWinPaneFrame    *winFrame = cli->framewin;
  738. X
  739. X    if (!pxcre)
  740. X    return winInfo->core.dirtyconfig;
  741. X    WinRootPos(winInfo, &oldX, &oldY);
  742. X    oldWidth = winInfo->core.width;
  743. X    oldHeight = winInfo->core.height;
  744. X
  745. X    if ((pxcre->value_mask & CWHeight) && (pxcre->height != oldHeight)) {
  746. X    winInfo->core.height = pxcre->height;
  747. X    winInfo->core.dirtyconfig |= CWHeight;
  748. X    }
  749. X    if ((pxcre->value_mask & CWWidth) && (pxcre->width != oldWidth)) {
  750. X    winInfo->core.width = pxcre->width;
  751. X    winInfo->core.dirtyconfig |= CWWidth;
  752. X    }
  753. X    /*if (pxcre->value_mask & CWBorderWidth)
  754. X    winFrame->pcore.oldBorderWidth = pxcre->border_width;*/
  755. X    if (pxcre->value_mask & (CWX|CWY))
  756. X    FrameSetPosAbsolute(winFrame,
  757. X                (pxcre->value_mask & CWX) ? (pxcre->x) : oldX,
  758. X                (pxcre->value_mask & CWY) ? (pxcre->y) : oldY);
  759. X    if (pxcre->value_mask & (CWStackMode | CWSibling))
  760. X    GFrameSetStack(winFrame, pxcre->value_mask, pxcre->detail, pxcre->above);
  761. X    return winInfo->core.dirtyconfig;
  762. X}
  763. X    
  764. Xstatic
  765. XvdmButtonPress(dpy, event, winInfo)
  766. X    Display    *dpy;
  767. X    XEvent    *event;
  768. X    WinGeneric    *winInfo;
  769. X{
  770. Xstatic VDMstuff    stuff;
  771. XSemanticAction    a;
  772. XScreenInfo    *scrInfo = winInfo->core.client->scrInfo;
  773. X
  774. X    a = ResolveMouseBinding(dpy, event, ModMaskMap[MOD_CONSTRAIN] |
  775. X                    ModMaskMap[MOD_INVERT] |
  776. X                    ModMaskMap[MOD_REDUCE]);
  777. X    switch(a) {
  778. X    case ACTION_SELECT:
  779. X            stuff.vdm = scrInfo->vdm;
  780. X            stuff.pointerX = event->xbutton.x;
  781. X            stuff.pointerY = event->xbutton.y;
  782. X            stuff.gc = scrInfo->gc[ROOT_GC];
  783. X            stuff.initX = scrInfo->vdm->screenX;
  784. X            stuff.initY = scrInfo->vdm->screenY;
  785. X            stuff.numMoves = 0;
  786. X            XDrawRectangle(stuff.vdm->client->dpy,
  787. X               PANEWINOFCLIENT(stuff.vdm->client),
  788. X                  stuff.gc, stuff.vdm->screenX, stuff.vdm->screenY,
  789. X                  stuff.vdm->screenWidth + 1, stuff.vdm->screenHeight);
  790. X            InstallInterposer(vdmInterposer, &stuff);
  791. X        break;
  792. X    case ACTION_MENU:
  793. X        MenuShowSync(dpy, winInfo, scrInfo->menuTable[MENU_VDM],
  794. X             event, NULL, NULL, False, False);
  795. X        break;
  796. X    }
  797. X}
  798. X
  799. Xstatic
  800. XvdmRedraw(dpy, win)
  801. X    Display    *dpy;
  802. X    WinGeneric    *win;
  803. X{
  804. X    drawVDMGrid(win->core.client->dpy, win->core.client->scrInfo->vdm);
  805. X}
  806. X
  807. Xstatic
  808. XvdmExit()
  809. X{
  810. X    fprintf(stderr, "VDM destroy\n");
  811. X}
  812. X
  813. Xstatic
  814. XvdmButtonRelease()
  815. X{
  816. X/*
  817. X * Need this for middle button presses
  818. X */
  819. X}
  820. X
  821. Xstatic
  822. XvdmSetConfigure(dpy, winInfo)
  823. X    Display    *dpy;
  824. X    WinVirtual    *winInfo;
  825. X{
  826. XXConfigureEvent    ce;
  827. XXWindowChanges    xwc;
  828. X
  829. X    if (winInfo->core.dirtyconfig) {
  830. X    xwc.x = winInfo->core.x;
  831. X    xwc.y = winInfo->core.y;
  832. X    xwc.width = winInfo->core.width;
  833. X    xwc.height = winInfo->core.height;
  834. X    ConfigureWindow(dpy, winInfo,
  835. X             winInfo->core.dirtyconfig, &xwc);
  836. X    winInfo->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight);
  837. X    }
  838. X    ce.type = ConfigureNotify;
  839. X    ce.serial = 0L;
  840. X    ce.event = winInfo->core.self;
  841. X    ce.window = winInfo->core.self;
  842. X    WinRootPos(winInfo, &ce.x, &ce.y);
  843. X    ce.width = winInfo->core.width;
  844. X    ce.height = winInfo->core.height;
  845. X    ce.border_width = 0;
  846. X    ce.above = None;
  847. X    ce.override_redirect = False;
  848. X    /* 
  849. X     * Elsewhere, we send a configure event to the client, but since the
  850. X     * client is us, let's just call that function directly . . .
  851. X     */
  852. X    vdmConfigure(dpy, &ce, winInfo);
  853. X}
  854. X
  855. Xstatic
  856. XvdmButtonMotion()
  857. X{
  858. X/*
  859. X * Need this for middle button presses
  860. X */
  861. X}
  862. X
  863. Xstatic vdmNewpos(win, x, y)
  864. X    WinVirtual    *win;
  865. X    int        x, y;
  866. X{
  867. X    if (win->core.x != x) {
  868. X    win->core.x = x;
  869. X    win->core.dirtyconfig |= CWX;
  870. X    }
  871. X    if (win->core.y != y) {
  872. X    win->core.y = y;
  873. X    win->core.dirtyconfig |= CWY;
  874. X    }
  875. X    return win->core.dirtyconfig;
  876. X}
  877. X
  878. Xstatic vdmSelect()
  879. X{
  880. X}
  881. X
  882. Xstatic
  883. XwinIntNullFunc()
  884. X{
  885. X    fprintf(stderr, "WinIntNULL!\n");
  886. X}
  887. X
  888. X/*
  889. X * setsizePane - set the pane to a particular size, and initiate a reconfigure
  890. X */
  891. Xstatic int
  892. XvdmSetSize(win,w,h)
  893. XWinVirtual *win;
  894. Xint w, h;
  895. X{
  896. X    if (win->core.width != w) {
  897. X    win->core.width = w;
  898. X    win->core.dirtyconfig |= CWWidth;
  899. X    }
  900. X
  901. X    if (win->core.height != h) {
  902. X    win->core.height = h;
  903. X    win->core.dirtyconfig |= CWHeight;
  904. X    }
  905. X}   
  906. X
  907. X/*
  908. X * Callback function when VDM frame is mapped
  909. X */
  910. Xstatic
  911. XvdmSetupFrame(win, cli, frame)
  912. X    WinGeneric        *win;
  913. X    Client        *cli;
  914. X    WinGenericFrame    *frame;
  915. X{
  916. X    frame->fcore.panewin = (WinGenericPane *) win;
  917. X    cli->scrInfo->vdm->client = cli;
  918. X    cli->sticky = True;
  919. X    cli->flags |= CLOlwmOwned;
  920. X    win->core.parent = (WinGeneric *) frame;
  921. X    WinAddChild(frame, win);
  922. X    XReparentWindow(cli->dpy, win->core.self, frame->core.self,
  923. X            win->core.x, win->core.y);
  924. X    cli->wmHints->icon_pixmap = XCreateBitmapFromData(cli->dpy,
  925. X                RootWindow(cli->dpy, cli->screen), vdm_bits,
  926. X                vdm_width, vdm_height);
  927. X    cli->wmHints->icon_mask = XCreateBitmapFromData(cli->dpy,
  928. X                RootWindow(cli->dpy, cli->screen), vdmmask_bits,
  929. X                vdmmask_width, vdmmask_height);
  930. X}
  931. X
  932. Xstatic
  933. XvdmComputeWidth(dpy, event, winInfo)
  934. X    Display    *dpy;
  935. X    XEvent    *event;
  936. X    WinGeneric    *winInfo;
  937. X{
  938. X}
  939. X
  940. Xstatic
  941. XvdmComputeHeight(dpy, event, winInfo)
  942. X    Display    *dpy;
  943. X    XEvent    *event;
  944. X    WinGeneric    *winInfo;
  945. X{
  946. X}
  947. X
  948. X/*
  949. X * =======================================================================
  950. X * VDM Service Functions
  951. X */
  952. X
  953. XRedrawVDM(vdm)
  954. X    VirtualDesktop    *vdm;
  955. X{
  956. X    drawVDMGrid(vdm->client->dpy, vdm);
  957. X}
  958. X
  959. XVirtualInit(dpy)
  960. X    Display    *dpy;
  961. X
  962. X{
  963. X    classVirtualPane.core.kind = WIN_VIRTUAL;
  964. X    classVirtualPane.core.xevents[KeyPress] = vdmKeyPress;
  965. X    classVirtualPane.core.xevents[ButtonPress] = vdmButtonPress;
  966. X    classVirtualPane.core.xevents[ButtonRelease] = vdmButtonRelease;
  967. X    classVirtualPane.core.xevents[MotionNotify] = vdmButtonMotion;
  968. X    classVirtualPane.core.xevents[ConfigureNotify] = vdmConfigure;
  969. X    classVirtualPane.core.xevents[Expose] = vdmExpose;
  970. X    classVirtualPane.core.focusfunc = NULL;
  971. X    classVirtualPane.core.drawfunc = vdmRedraw;
  972. X    classVirtualPane.core.destroyfunc = vdmExit;
  973. X    classVirtualPane.core.selectfunc = vdmSelect;
  974. X    classVirtualPane.core.newconfigfunc = vdmNewConfigure;
  975. X    classVirtualPane.core.newposfunc = vdmNewpos;
  976. X    classVirtualPane.core.setconfigfunc = vdmSetConfigure;
  977. X    classVirtualPane.core.createcallback = vdmSetupFrame;
  978. X    classVirtualPane.core.heightfunc = vdmComputeHeight;
  979. X    classVirtualPane.core.widthfunc = vdmComputeWidth;
  980. X    classVirtualPane.pcore.setsizefunc = vdmSetSize;
  981. X}
  982. X
  983. X/*
  984. X * Create an instance of the VDM -- this creates the logical virtual desktop
  985. X * and then creates the VDM representation of it.
  986. X */
  987. X
  988. XMakeVDM(dpy, scrInfo, client, rsc)
  989. X    Display        *dpy;
  990. X    ScreenInfo        *scrInfo;
  991. X    Client        *client;
  992. X    VirtualResources    *rsc;
  993. X
  994. X{
  995. Xstatic XTextProperty    wName = {(unsigned char *) "Virtual Desktop",
  996. X                    XA_STRING, 8, 15 };
  997. Xstatic XTextProperty    iName = {(unsigned char *) "Desktop",
  998. X                    XA_STRING, 8, 7 };
  999. X    XSetWindowAttributes attr;
  1000. X    XSizeHints *sizeHints;
  1001. X    XWMHints *wmHints;
  1002. X    XClassHint *classHints;
  1003. X    unsigned attrMask;
  1004. X    int    win;
  1005. X    WinVirtual        *w;
  1006. X    VirtualDesktop    *v;
  1007. X    char    title[20];
  1008. X    Button    *vdmButtons[9];
  1009. X
  1010. X    v = allocVirtualDesktop(dpy, scrInfo->screen, rsc);
  1011. X    w = MemNew(WinVirtual);
  1012. X
  1013. X    sizeHints = XAllocSizeHints();
  1014. X    sizeHints->flags = PBaseSize;
  1015. X    sizeHints->base_width = v->width;
  1016. X    sizeHints->base_height = v->height;
  1017. X    sizeHints->min_width = v->screenWidth;
  1018. X    sizeHints->min_height = v->screenHeight;
  1019. X    if (rsc->grid) {
  1020. X    sizeHints->flags = PMinSize | PResizeInc;
  1021. X        sizeHints->width_inc = v->screenWidth;
  1022. X        sizeHints->height_inc = v->screenHeight;
  1023. X    }
  1024. X    else sizeHints->flags = PMinSize;
  1025. X
  1026. X    /* REMIND Add an icon file attrbute */
  1027. X    wmHints = XAllocWMHints();
  1028. X    if (GRV.VirtualIconic)
  1029. X    wmHints->initial_state = IconicState;
  1030. X    else wmHints->initial_state = NormalState;
  1031. X    wmHints->flags = StateHint | InputHint | IconWindowHint;
  1032. X    wmHints->input = False;
  1033. X
  1034. X    wmHints->icon_window = XCreateSimpleWindow(dpy,
  1035. X                RootWindow(dpy, scrInfo->screen),
  1036. X                0, 0, vdm_width, vdm_height, 0, 0,
  1037. X                scrInfo->colorInfo.workspaceRootPixel);
  1038. X
  1039. X    classHints = XAllocClassHint();
  1040. X    classHints->res_name = "virtualDesktop";
  1041. X    classHints->res_class = "olvwm";
  1042. X    attrMask = CWEventMask;
  1043. X
  1044. X    if (DefaultDepth(dpy, scrInfo->screen) == 1) {
  1045. X        attrMask |= CWBackPixmap;
  1046. X        attr.background_pixmap = XCreatePixmapFromBitmapData(dpy,
  1047. X            RootWindow(dpy, scrInfo->screen),
  1048. X            pixdata, 8, 2,
  1049. X            scrInfo->colorInfo.fgColor, scrInfo->colorInfo.bgColor,
  1050. X            1);
  1051. X    }
  1052. X    else if (!rsc->background) {
  1053. X        attrMask |= CWBackPixel;
  1054. X        attr.background_pixel = scrInfo->colorInfo.virtualBgColor;
  1055. X    }
  1056. X    else {
  1057. X    attrMask |= CWBackPixmap;
  1058. X    attr.background_pixmap = VirtualGetPixmap(dpy, scrInfo, rsc->background);
  1059. X    }
  1060. X    attr.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask |
  1061. X              ButtonMotionMask | KeyPressMask;
  1062. X
  1063. X    w->class = &classVirtualPane;
  1064. X    w->core.kind = WIN_VIRTUAL;
  1065. X    w->core.children = NULL;
  1066. X    w->core.client = client;
  1067. X    w->core.x = sizeHints->x;
  1068. X    w->core.y = sizeHints->y;
  1069. X    w->core.width = sizeHints->base_width;
  1070. X    w->core.height = sizeHints->base_height;
  1071. X    w->core.dirtyconfig = CWX | CWY | CWWidth | CWHeight;
  1072. X    w->core.exposures = NULL;
  1073. X    w->core.helpstring = "olvwm:VDM";
  1074. X    w->core.colormap = NULL;        /* initialized in callback */
  1075. X
  1076. X    w->core.self = XCreateWindow(dpy, RootWindow(dpy, scrInfo->screen),
  1077. X                    sizeHints->x, sizeHints->y,
  1078. X                        sizeHints->base_width, sizeHints->base_height,
  1079. X                0,
  1080. X            /* REMIND olwm visual affects this? */
  1081. X                        DefaultDepth(dpy, scrInfo->screen), InputOutput,
  1082. X                        CopyFromParent, attrMask, &attr);
  1083. X    XSetWMProperties(dpy, w->core.self, &wName, &iName, NULL, 0,
  1084. X                 sizeHints, wmHints, classHints);
  1085. X
  1086. X    WIInstallInfo((WinGeneric *)w);
  1087. X    scrInfo->vdm = v;
  1088. X    v->client = StateNew(dpy, RootWindow(dpy, scrInfo->screen), w->core.self, False, w);
  1089. X    /*
  1090. X     * Sigh -- the call back was called before the icon frame was created
  1091. X     * so we can't do this there like we'd like to.  And it was called
  1092. X     * after StateNew processes the wmHints . . .
  1093. X     */
  1094. X    ((WinIconPane *) v->client->iconwin->fcore.panewin)->iconPixmap =
  1095. X                    v->client->wmHints->icon_pixmap;
  1096. X    ((WinIconPane *) v->client->iconwin->fcore.panewin)->iconMask =
  1097. X                    v->client->wmHints->icon_mask;
  1098. X    VirtualSetGeometry(v->client->framewin,
  1099. X               v->client->scrInfo->vdm->resources->geometry);
  1100. X    VirtualSetGeometry(v->client->iconwin,
  1101. X               v->client->scrInfo->vdm->resources->iconGeometry);
  1102. X
  1103. X    /*
  1104. X     * Make the VDMs menu
  1105. X     */
  1106. X    sprintf(title, "OLVWM 3.%0d", PATCHLEVELv3);
  1107. X    vdmButtons[0] = MakeUpLeftButton(dpy, scrInfo);
  1108. X    vdmButtons[1] = MakeLeftButton(dpy, scrInfo);
  1109. X    vdmButtons[2] = MakeDownLeftButton(dpy, scrInfo);
  1110. X    vdmButtons[3] = MakeUpButton(dpy, scrInfo);
  1111. X    vdmButtons[4] = MakeHomeButton(dpy, scrInfo);
  1112. X    vdmButtons[5] = MakeDownButton(dpy, scrInfo);
  1113. X    vdmButtons[6] = MakeUpRightButton(dpy, scrInfo);
  1114. X    vdmButtons[7] = MakeRightButton(dpy, scrInfo);
  1115. X    vdmButtons[8] = MakeDownRightButton(dpy, scrInfo);
  1116. X    scrInfo->menuTable[MENU_VDM] = CreateMenu(strdup(title), vdmButtons,
  1117. X                sizeof(vdmButtons)/sizeof(vdmButtons[0]),
  1118. X                True, "olvwm:MotionMenu");
  1119. X    scrInfo->menuTable[MENU_VDM]->prefColSize = 3;
  1120. X    scrInfo->menuTable[MENU_VDM]->buttonDefault = 4;
  1121. X    (void) MenuInfoCreate(scrInfo->menuCache, scrInfo->rootwin,
  1122. X                  scrInfo->menuTable[MENU_VDM], 1);
  1123. X
  1124. X    XFree(sizeHints);
  1125. X    XFree(wmHints);
  1126. X    XFree(classHints);
  1127. X}
  1128. X
  1129. X/*
  1130. X * Create the virtual representation of the client's frame and icon
  1131. X */
  1132. XMakeVirtual(cli)
  1133. X    Client    *cli;
  1134. X
  1135. X{
  1136. Xint    width, height;
  1137. Xint    x, y;
  1138. XWindow    virtual;
  1139. X
  1140. X    /*
  1141. X     * Subtract 1 for those window borders
  1142. X     */
  1143. X    width = cli->framewin->core.width / cli->scrInfo->vdm->resources->scale - 1;
  1144. X    height = cli->framewin->core.height / cli->scrInfo->vdm->resources->scale-1;
  1145. X
  1146. X    x = cli->framewin->core.x / cli->scrInfo->vdm->resources->scale +
  1147. X            cli->scrInfo->vdm->screenX;
  1148. X    y = cli->framewin->core.y / cli->scrInfo->vdm->resources->scale +
  1149. X            cli->scrInfo->vdm->screenY;
  1150. X
  1151. X    if (width <= 0)
  1152. X    width = 1;
  1153. X    if (height <= 0)
  1154. X    height = 1;
  1155. X    virtual = XCreateSimpleWindow(cli->dpy,
  1156. X        PANEWINOFCLIENT(cli->scrInfo->vdm->client),
  1157. X        x, y, width, height, 1, cli->scrInfo->colorInfo.borderColor,
  1158. X        cli->scrInfo->colorInfo.virtualFgColor);
  1159. X    if (PANEWINOFCLIENT(cli) != PANEWINOFCLIENT(cli->scrInfo->vdm->client))
  1160. X        XSelectInput(cli->dpy, virtual, VDMSelectMask);
  1161. X    else XSelectInput(cli->dpy, virtual, ExposureMask);
  1162. X    cli->framewin->core.virtual = virtual;
  1163. X    VInstallInfo(cli->framewin);
  1164. X    MakeVirtualIcon(cli);
  1165. X}
  1166. X
  1167. XMakeVirtualIcon(cli)
  1168. X    Client    *cli;
  1169. X
  1170. X{
  1171. Xint    width, height;
  1172. Xint    x, y;
  1173. X
  1174. X    width = cli->iconwin->core.width / cli->scrInfo->vdm->resources->scale;
  1175. X    height = cli->iconwin->core.height / cli->scrInfo->vdm->resources->scale;
  1176. X
  1177. X    x = cli->iconwin->core.x / cli->scrInfo->vdm->resources->scale +
  1178. X            cli->scrInfo->vdm->screenX;
  1179. X    y = cli->iconwin->core.y / cli->scrInfo->vdm->resources->scale +
  1180. X            cli->scrInfo->vdm->screenY;
  1181. X
  1182. X    if (width <= 0)
  1183. X    width = 1;
  1184. X    if (height <= 0)
  1185. X    height = 1;
  1186. X    cli->iconwin->core.virtual = XCreateSimpleWindow(cli->dpy,
  1187. X                    PANEWINOFCLIENT(cli->scrInfo->vdm->client),
  1188. X                    x, y, width, height, 1,
  1189. X                    cli->scrInfo->colorInfo.borderColor,
  1190. X                    cli->scrInfo->colorInfo.virtualFgColor);
  1191. X    XSelectInput(cli->dpy, cli->iconwin->core.virtual, VDMSelectMask);
  1192. X    VInstallInfo(cli->iconwin);
  1193. X}
  1194. X
  1195. X/*
  1196. X * Call to set/unset the focus of the given window
  1197. X */
  1198. XVirtualChangeFocus(win, focus)
  1199. X    WinGenericFrame    *win;
  1200. X    Bool        focus;
  1201. X{
  1202. Xint    length;
  1203. X
  1204. X    switch(win->core.kind) {
  1205. X    case WIN_ICON:
  1206. X        length = ((WinIconFrame *) win)->nameLength;
  1207. X        break;
  1208. X    case WIN_FRAME:
  1209. X        length = ((WinPaneFrame *) win)->nameLength;
  1210. X        break;
  1211. X    default:
  1212. X        return;
  1213. X    }
  1214. X    if (focus)
  1215. X    XSetWindowBackground(win->core.client->dpy, win->core.virtual,
  1216. X            win->core.client->scrInfo->colorInfo.virtualInputColor);
  1217. X    else XSetWindowBackground(win->core.client->dpy, win->core.virtual,
  1218. X            win->core.client->scrInfo->colorInfo.virtualFgColor);
  1219. X    XClearWindow(win->core.client->dpy, win->core.virtual);
  1220. X    XDrawImageString(win->core.client->dpy, win->core.virtual,
  1221. X             (focus) ? win->core.client->scrInfo->gc[VDM_INPUT_GC] :
  1222. X                   win->core.client->scrInfo->gc[VDM_GC],
  1223. X             1, win->core.client->scrInfo->vdm->max_ascent + 1,
  1224. X             win->fcore.name, length);
  1225. X}
  1226. X
  1227. X/*
  1228. X * Refresh the window's virtual representation
  1229. X */
  1230. XPaintVirtualWindow(win)
  1231. X    WinGenericFrame    *win;
  1232. X{
  1233. XClient    *cli = win->core.client;
  1234. Xint    length;
  1235. X
  1236. X    switch(win->core.kind) {
  1237. X    case WIN_ICON:
  1238. X        length = ((WinIconFrame *) win)->nameLength;
  1239. X        break;
  1240. X    case WIN_FRAME:
  1241. X        length = ((WinPaneFrame *) win)->nameLength;
  1242. X        break;
  1243. X    default:
  1244. X        return;
  1245. X    }
  1246. X    XClearArea(cli->dpy, win->core.virtual, 0, 0, 0, 0, False);
  1247. X    XDrawImageString(cli->dpy, win->core.virtual,
  1248. X             (cli->isFocus) ? cli->scrInfo->gc[VDM_INPUT_GC] :
  1249. X                   cli->scrInfo->gc[VDM_GC],
  1250. X             1, cli->scrInfo->vdm->max_ascent + 1,
  1251. X             win->fcore.name, length);
  1252. X}
  1253. X
  1254. X/*
  1255. X * Dispatch the event to its virtual window if it belongs to a virtual window
  1256. X */
  1257. XDispatchVirtual(dpy, event)
  1258. X    Display    *dpy;
  1259. X    XEvent    *event;
  1260. X{
  1261. XWinGeneric    *win, *VGetInfo();
  1262. Xstatic SemanticAction    currentVDMAction;
  1263. Xunsigned int    ignoremask;
  1264. X
  1265. X    if (event->xany.type == KeymapNotify || event->xany.type == MappingNotify)
  1266. X    return False;
  1267. X    win = VGetInfo(event->xany.window);
  1268. X    if (!win)
  1269. X    return False;
  1270. X    switch(event->xany.type) {
  1271. X    case Expose:
  1272. X        PaintVirtualWindow(win);
  1273. X        break;
  1274. X
  1275. X    /*
  1276. X     * For mouse events, we generally try to pretend that the mouse event
  1277. X     * happened on the frame instead of on the virtual window.
  1278. X     * We pretend that adjust and select events occured on the frame
  1279. X     * and just pass them to the frame's routine (after translating
  1280. X     * the root coordinates).  But we don't translate root coordinates
  1281. X     * for menus because we want the menu to come up where the mouse
  1282. X     * was
  1283. X     */
  1284. X    case ButtonPress:
  1285. X            ignoremask = ModMaskMap[MOD_CONSTRAIN] |
  1286. X                 ModMaskMap[MOD_INVERT] |
  1287. X                ModMaskMap[MOD_REDUCE];
  1288. X        currentVDMAction = ResolveMouseBinding(dpy, event, ignoremask);
  1289. X        if (currentVDMAction == ACTION_NONE)
  1290. X        return True;
  1291. X        if ((currentVDMAction == ACTION_SELECT) &&
  1292. X        (event->xbutton.time - lastSelectTime <= GRV.DoubleClickTime)) {
  1293. X        /*
  1294. X         * We have a double click in the VDM.  This is an exception to
  1295. X         * the above rule:  if we pass this to the frame, then the
  1296. X         * frame will go full size, which is not very interesting.
  1297. X         * So for this one we pretend it's a double click in the
  1298. X         * VDM itself
  1299. X         */
  1300. X            translateVirtualCoords(win->core.client->scrInfo->vdm,
  1301. X                &event->xmotion.x_root, &event->xmotion.y_root,
  1302. X                &event->xmotion.x, &event->xmotion.y);
  1303. X        VDMMoveTo(win->core.client->dpy, win->core.client,
  1304. X              event->xbutton.x_root, event->xbutton.y_root);
  1305. X        return True;
  1306. X        }
  1307. X        if (currentVDMAction == ACTION_MENU)
  1308. X            translateVirtualCoords(win->core.client->scrInfo->vdm,
  1309. X                       NULL, NULL,
  1310. X                       &event->xmotion.x, &event->xmotion.y);
  1311. X        else translateVirtualCoords(win->core.client->scrInfo->vdm,
  1312. X                &event->xmotion.x_root, &event->xmotion.y_root,
  1313. X                &event->xmotion.x, &event->xmotion.y);
  1314. X        GFrameEventButtonPress(dpy, event, win);
  1315. X        break;
  1316. X    
  1317. X    case MotionNotify:
  1318. X        translateVirtualCoords(win->core.client->scrInfo->vdm,
  1319. X                &event->xmotion.x_root, &event->xmotion.y_root,
  1320. X                &event->xmotion.x, &event->xmotion.y);
  1321. X        GFrameEventMotionNotify(dpy, event, win);
  1322. X        break;
  1323. X
  1324. X    case ButtonRelease:
  1325. X        if (currentVDMAction == ACTION_NONE)
  1326. X        return True;
  1327. X        if (currentVDMAction == ACTION_MENU)
  1328. X            translateVirtualCoords(win->core.client->scrInfo->vdm,
  1329. X                       NULL, NULL,
  1330. X                       &event->xmotion.x, &event->xmotion.y);
  1331. X        else translateVirtualCoords(win->core.client->scrInfo->vdm,
  1332. X                &event->xmotion.x_root, &event->xmotion.y_root,
  1333. X                &event->xmotion.x, &event->xmotion.y);
  1334. X        GFrameEventButtonRelease(dpy, event, win);
  1335. X        if (currentVDMAction == ACTION_SELECT)
  1336. X        lastSelectTime = event->xbutton.time;
  1337. X        currentVDMAction = ACTION_NONE;
  1338. X        break;
  1339. X
  1340. X    default:
  1341. X        fprintf(stderr, "unwanted %d event\n", event->xany.type);
  1342. X        break;
  1343. X    }
  1344. X    return True;
  1345. X}
  1346. X
  1347. XMakeSticky(cli, sticky)
  1348. X    Client    *cli;
  1349. X    Bool    sticky;
  1350. X
  1351. X{
  1352. Xint    dw, dh, x, y;
  1353. X    /*
  1354. X     * Can't unstick the VDM
  1355. X     */
  1356. X    if (cli->groupid == PANEWINOFCLIENT(cli->scrInfo->vdm->client) && !sticky)
  1357. X    return !NULL;
  1358. X    cli->sticky = sticky;
  1359. X    dw = DisplayWidth(cli->dpy, cli->screen);
  1360. X    dh = DisplayHeight(cli->dpy, cli->screen);
  1361. X    if (cli->sticky) {
  1362. X    x = cli->framewin->core.x;
  1363. X    y = cli->framewin->core.y;
  1364. X    cli->framewin->core.dirtyconfig |= CWX;
  1365. X    GFrameSetConfig(cli->framewin, x, y,
  1366. X            cli->framewin->core.width, cli->framewin->core.height);
  1367. X
  1368. X    x = cli->iconwin->core.x;
  1369. X    y = cli->iconwin->core.y;
  1370. X    cli->iconwin->core.dirtyconfig |= CWX;
  1371. X    IconSetPos(cli->iconwin, x + ICON_HORZBORDER, y + ICON_VERTBORDER);
  1372. X    WinCallConfig(cli->dpy, cli->iconwin, NULL);
  1373. X    }
  1374. X    return NULL;
  1375. X}
  1376. X
  1377. X/*
  1378. X * Return true if the given key action should affect the VDM
  1379. X */
  1380. XKeyMoveVDM(dpy, ev)
  1381. X    Display *dpy;
  1382. X    XEvent  *ev;
  1383. X{
  1384. XVirtualDesktop    *vdm;
  1385. XWinGeneric    *root;
  1386. XSemanticAction    a;
  1387. X
  1388. X    if (ev->xany.type != KeyPress)
  1389. X    /* Root window uses same function for Up and Down events */
  1390. X    return False;
  1391. X
  1392. X    root = WIGetInfo(ev->xkey.root);
  1393. X    if (!root) {
  1394. X    fprintf(stderr, "NO ROOT\n");
  1395. X    return False;
  1396. X    }
  1397. X    if (!root->core.client) {
  1398. X    fprintf(stderr, "NO CLIENT\n");
  1399. X    return False;
  1400. X    }
  1401. X    if (!root->core.client->scrInfo) {
  1402. X    fprintf(stderr, "NO SCRINFO\n");
  1403. X    return False;
  1404. X    }
  1405. X    vdm = root->core.client->scrInfo->vdm;
  1406. X
  1407. X    a = FindNewKeyboardAction(dpy, ev);
  1408. X    if (a == ACTION_NONE)
  1409. X    return False;
  1410. X    if (a == ACTION_VIRTUAL)
  1411. X    return CheckForKeyProg(dpy, ev);
  1412. X
  1413. X    return vdmPerformAction(dpy, vdm, a);
  1414. X}
  1415. X
  1416. X/*
  1417. X * Update the selection state of the given window's virtual representation
  1418. X */
  1419. XVirtualSelect(win, sel)
  1420. X    WinGeneric    *win;
  1421. X    Bool    sel;
  1422. X
  1423. X{
  1424. X    if (win->core.virtual)
  1425. X    XSetWindowBorderWidth(win->core.client->dpy,
  1426. X                  win->core.virtual, (sel) ? 2 : 1);
  1427. X}
  1428. X
  1429. X/*
  1430. X * Move to point x, y and save the desktop; we do this when save workspace
  1431. X * is called so that all the coordinates will be correct for startup
  1432. X * position
  1433. X */
  1434. XVirtualSaveDesktops(dpy, x, y)
  1435. X    Display    *dpy;
  1436. X    int        x, y;
  1437. X{
  1438. Xstruct deltas    deltas;
  1439. XScreenInfo    *si;
  1440. XList        *l = ScreenInfoList;
  1441. X
  1442. X    for (si = ListEnum(&l); si; si = ListEnum(&l)) {
  1443. X        si->vdm->saveX = si->vdm->offsetX;
  1444. X        si->vdm->saveY = si->vdm->offsetY;
  1445. X        deltas.delta_x = si->vdm->offsetX - x;
  1446. X        deltas.delta_y = si->vdm->offsetY - y;
  1447. X        moveDesktop(dpy, &deltas, si->vdm);
  1448. X    }
  1449. X}
  1450. X
  1451. XVirtualRestoreDesktops(dpy)
  1452. X    Display    *dpy;
  1453. X{
  1454. Xstruct deltas    deltas;
  1455. XScreenInfo    *si;
  1456. XList        *l = ScreenInfoList;
  1457. X
  1458. X    for (si = ListEnum(&l); si; si = ListEnum(&l)) {
  1459. X        deltas.delta_x = -si->vdm->saveX;
  1460. X        deltas.delta_y = -si->vdm->saveY;
  1461. X        moveDesktop(dpy, &deltas, si->vdm);
  1462. X    }
  1463. X}
  1464. X
  1465. XVirtualCleanup(dpy)
  1466. X    Display    *dpy;
  1467. X
  1468. X{
  1469. X    VirtualSaveDesktops(dpy, 0, 0);
  1470. X}
  1471. X
  1472. XResizeVDM(vdm, size)
  1473. X    VirtualDesktop    *vdm;
  1474. X    char        *size;
  1475. X{
  1476. XWinGenericFrame    *win;
  1477. X
  1478. X    win = (WinGenericFrame *) vdm->client->framewin;
  1479. X    if (vdm->resources->size)
  1480. X    free(vdm->resources->size);
  1481. X    vdm->resources->size = strdup(size);
  1482. X    calculateVirtualDesktopSize(vdm->client->dpy, vdm->client->screen, vdm);
  1483. X    GFrameSetConfig(win, win->core.x, win->core.y,
  1484. X        vdm->width + (WinFunc(win,fcore.widthleft))(win) +
  1485. X                 (WinFunc(win,fcore.widthright))(win),
  1486. X        vdm->height + (WinFunc(win,fcore.heighttop))(win) +
  1487. X                 (WinFunc(win,fcore.heightbottom))(win));
  1488. X}
  1489. X
  1490. X/*
  1491. X *============================================================================
  1492. X *
  1493. X * Functions to reflect resources changes
  1494. X */
  1495. X
  1496. Xstatic void *
  1497. XremakeVirtual(cli)
  1498. X    Client    *cli;
  1499. X{
  1500. XDisplay    *dpy = cli->dpy;
  1501. X
  1502. X    if (cli->framewin) {
  1503. X    VIUninstallInfo(cli->framewin->core.virtual);
  1504. X    VIUninstallInfo(cli->iconwin->core.virtual);
  1505. X    XDestroyWindow(dpy, cli->framewin->core.virtual);
  1506. X    XDestroyWindow(dpy, cli->iconwin->core.virtual);
  1507. X    MakeVirtual(cli);
  1508. X    XMapWindow(dpy, (cli->wmState == IconicState) ?
  1509. X                cli->iconwin->core.virtual :
  1510. X                cli->framewin->core.virtual);
  1511. X    }
  1512. X    return NULL;
  1513. X}
  1514. X
  1515. Xstatic void *
  1516. XupdateVirtualWindow(cli)
  1517. X    Client    *cli;
  1518. X
  1519. X{
  1520. XDisplay    *dpy = cli->dpy;
  1521. X
  1522. X    if (cli->framewin) {
  1523. X    XSetWindowBackground(dpy, cli->framewin->core.virtual,
  1524. X                cli->scrInfo->colorInfo.virtualFgColor);
  1525. X    XSetWindowBackground(dpy, cli->iconwin->core.virtual,
  1526. X                cli->scrInfo->colorInfo.virtualFgColor);
  1527. X    }
  1528. X}
  1529. X
  1530. X/*
  1531. X * Resize the VDM with the new scale
  1532. X */
  1533. XRescaleVDM(vdm, scale)
  1534. X    VirtualDesktop    *vdm;
  1535. X    int            scale;
  1536. X
  1537. X{
  1538. Xint    orig_scale;
  1539. XWinGenericFrame    *win;
  1540. X
  1541. X    orig_scale = vdm->resources->scale;
  1542. X    vdm->resources->scale = scale;
  1543. X    calculateVirtualDesktopSize(vdm->client->dpy, vdm->client->screen, vdm);
  1544. X    vdm->screenX = (vdm->screenX * orig_scale) / scale;
  1545. X    vdm->screenY = (vdm->screenY * orig_scale) / scale;
  1546. X    vdm->client->normHints->width_inc = vdm->screenWidth;
  1547. X    vdm->client->normHints->height_inc = vdm->screenHeight;
  1548. X    win = (WinGenericFrame *) vdm->client->framewin;
  1549. X    GFrameSetConfig(win, win->core.x, win->core.y,
  1550. X        vdm->width + (WinFunc(win,fcore.widthleft))(win) +
  1551. X                     (WinFunc(win,fcore.widthright))(win),
  1552. X        vdm->height + (WinFunc(win,fcore.heighttop))(win) +
  1553. X                      (WinFunc(win,fcore.heightbottom))(win));
  1554. X    ListApply(ActiveClientList, remakeVirtual, 0);
  1555. X}
  1556. X
  1557. XVirtualUpdateVirtualWindows(cli)
  1558. X    Client    *cli;
  1559. X{
  1560. X    ListApply(ActiveClientList, updateVirtualWindow, 0);
  1561. X    ClientRefresh(cli);
  1562. X}
  1563. X
  1564. X/*
  1565. X * Size the VDM with the new geometry
  1566. X */
  1567. XVirtualSetGeometry(win, geom)
  1568. X    WinGeneric    *win;
  1569. X    char    *geom;
  1570. X{
  1571. Xint    changed;
  1572. Xint    newx, newy, x, y, w, h;
  1573. XDisplay    *dpy = win->core.client->dpy;
  1574. XScreenInfo    *scrInfo = win->core.client->scrInfo;
  1575. X
  1576. X        changed = XParseGeometry(geom, &x, &y, &w, &h);
  1577. X        if (changed & (XValue | YValue)) {
  1578. X            if (changed & XValue)
  1579. X                if (changed & XNegative)
  1580. X                    newx = DisplayWidth(dpy, scrInfo->screen) + x;
  1581. X                else newx = x;
  1582. X            else newx = win->core.x;
  1583. X        w = win->core.width;
  1584. X            if (newx > DisplayWidth(dpy, scrInfo->screen) - w)
  1585. X                newx = DisplayWidth(dpy, scrInfo->screen) - w;
  1586. X            if (changed & YValue)
  1587. X                if (changed & YNegative)
  1588. X                    newy = DisplayHeight(dpy, scrInfo->screen) + y;
  1589. X                else newy = y;
  1590. X            else newy = win->core.y;
  1591. X        h = win->core.height;
  1592. X            if (newy > DisplayHeight(dpy, scrInfo->screen) - h)
  1593. X                newy = DisplayHeight(dpy, scrInfo->screen) - h;
  1594. X            GFrameSetConfig(win, newx, newy, win->core.width, win->core.height);           
  1595. X        }
  1596. X}
  1597. X
  1598. X/*
  1599. X * Get a background pixmap for the VDM with the VDM colors
  1600. X */
  1601. XPixmap
  1602. XVirtualGetPixmap(dpy, scrInfo, name)
  1603. X    Display    *dpy;
  1604. X    ScreenInfo    *scrInfo;
  1605. X    char    *name;
  1606. X
  1607. X{
  1608. XPixmap    read, write;
  1609. Xint    w, h, dummy;
  1610. XXGCValues    gcv;
  1611. XGC    gc;
  1612. X
  1613. X    if (XReadBitmapFile(dpy, scrInfo->rootid, name,
  1614. X            &w, &h, &read, &dummy, &dummy) == BitmapSuccess) {
  1615. X    write = XCreatePixmap(dpy, scrInfo->rootid, w, h, scrInfo->depth);
  1616. X    gcv.function = GXcopy;
  1617. X    gc = XCreateGC(dpy, scrInfo->rootid, GCFunction, &gcv);
  1618. X    XSetForeground(dpy, gc, scrInfo->colorInfo.virtualPixmapColor);
  1619. X    XSetBackground(dpy, gc, scrInfo->colorInfo.virtualBgColor);
  1620. X    XCopyPlane(dpy, read, write, gc, 0, 0, w, h, 0, 0, 1);
  1621. X    XFreePixmap(dpy, read);
  1622. X    XFreeGC(dpy, gc);
  1623. X    return write;
  1624. X    }
  1625. X    else {
  1626. X    ErrorWarning(gettext("An invalid bitmap file was named as the virtual background"));
  1627. X    return None;
  1628. X    }
  1629. X}
  1630. X
  1631. X/*
  1632. X * Perform an action from the VDM menu
  1633. X */
  1634. Xint
  1635. XVDMMenuAction(dpy, winInfo, menuInfo, btn)
  1636. X    Display    *dpy;
  1637. X    WinPinMenu    *winInfo;
  1638. X    MenuInfo    *menuInfo;
  1639. X    int        btn;
  1640. X
  1641. X{
  1642. X
  1643. X    if (!vdmPerformAction(dpy, winInfo->core.client->scrInfo->vdm,
  1644. X                vdmButtonActions[btn]) && GRV.Beep == BeepAlways)
  1645. X    XBell(dpy, 100);
  1646. X}
  1647. X
  1648. X/*
  1649. X * Move to the logical screen on the desktop containing point x, y
  1650. X *
  1651. X * This move is constrained to a logical screen, even if the grid is
  1652. X * off.
  1653. X */
  1654. XVDMMoveTo(dpy, client, x, y)
  1655. X    Display    *dpy;
  1656. X    Client    *client;
  1657. X    int        x, y;
  1658. X{
  1659. Xint    dw, dh;
  1660. Xstruct deltas    deltas;
  1661. X
  1662. X    dw = DisplayWidth(dpy, client->screen);
  1663. X    dh = DisplayHeight(dpy, client->screen);
  1664. X    deltas.delta_x = ((x - client->scrInfo->vdm->offsetX) / dw) * dw
  1665. X            + client->scrInfo->vdm->offsetX;
  1666. X    deltas.delta_y = ((y - client->scrInfo->vdm->offsetY) / dh) * dh
  1667. X            + client->scrInfo->vdm->offsetY;
  1668. X    constrainDeltas(dpy, client->scrInfo->vdm, &deltas);
  1669. X    moveDesktop(dpy, &deltas, client->scrInfo->vdm);
  1670. X}
  1671. X
  1672. X/*
  1673. X * Goto logical screen passed 
  1674. X */
  1675. X
  1676. XVDMGoto(dpy, client, screen)
  1677. X    Display    *dpy;
  1678. X    Client    *client;
  1679. X    int        screen;
  1680. X{
  1681. Xint    dw, dh;
  1682. X
  1683. X    screen--;
  1684. X    dw = DisplayWidth(dpy, client->screen);
  1685. X    dh = DisplayHeight(dpy, client->screen);
  1686. X    VDMMoveTo(dpy, client, dw * (screen % client->scrInfo->vdm->rows) +
  1687. X                    client->scrInfo->vdm->offsetX,
  1688. X        dh * (screen / client->scrInfo->vdm->rows) +
  1689. X                    client->scrInfo->vdm->offsetY);
  1690. X}
  1691. X
  1692. X/*
  1693. X *==========================================================================
  1694. X *
  1695. X * Utility functions to replace window mapping, configuring, etc.; these
  1696. X * functions work just like their X counterparts but affect both the
  1697. X * X window and its virtual representation.
  1698. X */
  1699. X
  1700. XMapWindow(win)
  1701. X    WinGeneric    *win;
  1702. X{
  1703. X    XSetWindowBorderWidth(win->core.client->dpy,
  1704. X        win->core.virtual, (win->core.client->isSelected) ? 2 : 1);
  1705. X    XMapWindow(win->core.client->dpy, win->core.self);
  1706. X    XMapWindow(win->core.client->dpy, win->core.virtual);
  1707. X    if (GRV.VirtualRaiseVDM && win->core.client->scrInfo->vdm->client)
  1708. X    RaiseWindow(win->core.client->scrInfo->vdm->client->framewin);
  1709. X}
  1710. X
  1711. XUnmapWindow(win)
  1712. X    WinGeneric    *win;
  1713. X{
  1714. X    XUnmapWindow(win->core.client->dpy, win->core.self);
  1715. X    XUnmapWindow(win->core.client->dpy, win->core.virtual);
  1716. X}
  1717. X
  1718. XMapRaised(win)
  1719. X    WinGeneric    *win;
  1720. X{
  1721. X    XSetWindowBorderWidth(win->core.client->dpy,
  1722. X        win->core.virtual, (win->core.client->isSelected) ? 2 : 1);
  1723. X    XMapRaised(win->core.client->dpy, win->core.self);
  1724. X    XMapRaised(win->core.client->dpy, win->core.virtual);
  1725. X    if (GRV.VirtualRaiseVDM && win->core.client->scrInfo->vdm->client)
  1726. X    RaiseWindow(win->core.client->scrInfo->vdm->client->framewin);
  1727. X}
  1728. X
  1729. XRaiseWindow(win)
  1730. X    WinGeneric    *win;
  1731. X{
  1732. X    XRaiseWindow(win->core.client->dpy, win->core.self);
  1733. X    XRaiseWindow(win->core.client->dpy, win->core.virtual);
  1734. X    if (GRV.VirtualRaiseVDM &&
  1735. X    win->core.client->scrInfo->vdm->client &&
  1736. X    win->core.client->scrInfo->vdm->client &&
  1737. X  win->core.self != win->core.client->scrInfo->vdm->client->framewin->core.self)
  1738. X    RaiseWindow(win->core.client->scrInfo->vdm->client->framewin);
  1739. X}
  1740. X
  1741. XLowerWindow(win)
  1742. X    WinGeneric    *win;
  1743. X{
  1744. X    XLowerWindow(win->core.client->dpy, win->core.self);
  1745. X    XLowerWindow(win->core.client->dpy, win->core.virtual);
  1746. X    if (GRV.VirtualRaiseVDM)
  1747. X    RaiseWindow(win->core.client->scrInfo->vdm->client->framewin);
  1748. X}
  1749. X
  1750. XDestroyWindow(win)
  1751. X    WinGeneric    *win;
  1752. X{
  1753. X    XDestroyWindow(win->core.client->dpy, win->core.self);
  1754. X    WIUninstallInfo(win->core.self);
  1755. X    if (win->core.virtual)
  1756. X        XDestroyWindow(win->core.client->dpy, win->core.virtual);
  1757. X}
  1758. X
  1759. XDeleteProperty(dpy, win, atom)
  1760. X    Display        *dpy;
  1761. X    WinGenericFrame    *win;
  1762. X    Atom        atom;
  1763. X
  1764. X{
  1765. X    XDeleteProperty(dpy, win->core.self, atom);
  1766. X    if (win->core.virtual)
  1767. X        XDeleteProperty(dpy, win->core.virtual, atom);
  1768. X}
  1769. X
  1770. XChangeProperty(dpy, win, property, type, format, mode, data, nelements)
  1771. X   Display        *dpy;
  1772. X   WinGenericFrame    *win;
  1773. X   Atom            property, type;
  1774. X   int            format;
  1775. X   int            mode;
  1776. X   unsigned char    *data;
  1777. X   int            nelements;
  1778. X{
  1779. X    XChangeProperty(dpy, win->core.self, property, type, format,
  1780. X            mode, data, nelements);
  1781. X    if (win->core.virtual)
  1782. X        XChangeProperty(dpy, win->core.virtual, property, type, format,
  1783. X            mode, data, nelements);
  1784. X}
  1785. X
  1786. XConfigureWindow(dpy, win, mask, values)
  1787. X    Display    *dpy;
  1788. X    WinGeneric    *win;
  1789. X    int        mask;
  1790. X    XWindowChanges    *values;
  1791. X
  1792. X{
  1793. Xint    scale;
  1794. XWinGeneric    *tmp;
  1795. X
  1796. X    XConfigureWindow(dpy, win->core.self, mask, values);
  1797. X    scale = win->core.client->scrInfo->vdm->resources->scale;
  1798. X    if (mask & CWX)
  1799. X    values->x = (win->core.x - win->core.client->scrInfo->vdm->offsetX) /
  1800. X            scale;
  1801. X    if (mask & CWY)
  1802. X    values->y = (win->core.y - win->core.client->scrInfo->vdm->offsetY) /
  1803. X            scale;
  1804. X    if (mask & CWWidth)
  1805. X    values->width = win->core.width / scale;
  1806. X    if (mask & CWHeight)
  1807. X    values->height = win->core.height / scale;
  1808. X    if (mask & CWSibling) {
  1809. X    tmp = WIGetInfo(values->sibling);
  1810. X    if (tmp)
  1811. X        values->sibling = tmp->core.virtual;
  1812. X    else mask |= ~(CWSibling|CWStackMode);
  1813. X    }
  1814. X    XConfigureWindow(dpy, win->core.virtual, mask, values);
  1815. X    if (GRV.VirtualRaiseVDM)
  1816. X    RaiseWindow(win->core.client->scrInfo->vdm->client->framewin);
  1817. X}
  1818. X
  1819. X/*
  1820. X * Menu generation function for DIRMENU
  1821. X *
  1822. X */
  1823. XGenDirMenuFunc(dpy, menuInfo, bindex, cache, winInfo, depth)
  1824. X    Display    *dpy;
  1825. X    MenuInfo    *menuInfo;
  1826. X    int        bindex;
  1827. X    MenuCache    *cache;
  1828. X    WinGeneric    *winInfo;
  1829. X    int        depth;
  1830. X
  1831. X{
  1832. XMenu    *menu;
  1833. XDIR    *dir;
  1834. Xstruct dirent    *ent;
  1835. XButton    *b;
  1836. Xchar    s[256], *dirname;
  1837. Xextern int AppMenuFunc();
  1838. X
  1839. X    MenuInfoDestroy(menuInfo->buttons[bindex].subMenu);
  1840. X    menu = (Menu *) MemAlloc(sizeof(Menu));
  1841. X    menu->buttons = NULL;
  1842. X    menu->buttonCount = 0;
  1843. X    menu->buttonDefault = NOBUTTON;
  1844. X    menu->hasPushPin = False;
  1845. X    menu->menudirty = True;
  1846. X    menu->btnPerCol = 0;
  1847. X    menu->maxLabWidth = 0;
  1848. X    menu->prefColSize = 0;
  1849. X
  1850. X    dirname = (char *) menuInfo->menu->buttons[bindex]->generate_args;
  1851. X    if (!(dir = opendir(dirname))) {
  1852. X    menuInfo->buttons[bindex].subMenu =
  1853. X                MenuInfoCreate(cache, winInfo, menu, depth);
  1854. X    return;
  1855. X    }
  1856. X    while (ent = readdir(dir)) {
  1857. X    if (ent->d_name[0] == '.')
  1858. X        continue;
  1859. X    b = (Button *) MemAlloc(sizeof(Button));
  1860. X    if (!menu->buttonCount++)
  1861. X        menu->buttons = (Button **) MemAlloc(sizeof(Button *));
  1862. X    else menu->buttons = (Button **)
  1863. X        MemRealloc(menu->buttons, menu->buttonCount * sizeof(Button *));
  1864. X    menu->buttons[menu->buttonCount - 1] = b;
  1865. X    b->label[0].kind = StringLabel;
  1866. X    b->label[1].kind = NoType;
  1867. X    sprintf(s, "exec %s/%s", dirname, ent->d_name);
  1868. X    b->label[0].string = MemNewString(ent->d_name);
  1869. X    b->label[1].string = NULL;
  1870. X    b->helpstring[0] = b->helpstring[1] = NULL;
  1871. X    b->which = 0;
  1872. X    b->stacked = False;
  1873. X    b->enabled = True;
  1874. X    b->visible = True;
  1875. X    b->action.callback = AppMenuFunc;
  1876. X    b->action.submenu = (void *) MemNewString(s);
  1877. X    b->generate_func = NULL;
  1878. X    }
  1879. X    closedir(dir);
  1880. X    menuInfo->buttons[bindex].subMenu =
  1881. X                MenuInfoCreate(cache, winInfo, menu, depth);
  1882. X}
  1883. END_OF_FILE
  1884. if test 51849 -ne `wc -c <'virtual.c'`; then
  1885.     echo shar: \"'virtual.c'\" unpacked with wrong size!
  1886. fi
  1887. # end of 'virtual.c'
  1888. fi
  1889. echo shar: End of archive 2 \(of 21\).
  1890. cp /dev/null ark2isdone
  1891. MISSING=""
  1892. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  1893.     if test ! -f ark${I}isdone ; then
  1894.     MISSING="${MISSING} ${I}"
  1895.     fi
  1896. done
  1897. if test "${MISSING}" = "" ; then
  1898.     echo You have unpacked all 21 archives.
  1899.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1900. else
  1901.     echo You still need to unpack the following archives:
  1902.     echo "        " ${MISSING}
  1903. fi
  1904. ##  End of shell archive.
  1905. exit 0
  1906. --
  1907. Molecular Simulations, Inc.             mail: dcmartin@postgres.berkeley.edu
  1908. 796 N. Pastoria Avenue                  uucp: uwvax!ucbvax!dcmartin
  1909. Sunnyvale, California 94086             at&t: 408/522-9236
  1910.