WmCPlace.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * (c) Copyright 1989, 1990, 1991, 1992 OPEN SOFTWARE FOUNDATION, INC.
  25. * ALL RIGHTS RESERVED
  26. */
  27. /*
  28. * Motif Release 1.2
  29. */
  30. /*
  31. * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
  32. /*
  33. * Included Files:
  34. */
  35. #include "WmGlobal.h"
  36. #define XK_MISCELLANY
  37. #define XK_LATIN1
  38. #include <X11/keysymdef.h>
  39. /* absolute value macro */
  40. #ifndef ABS
  41. #define ABS(x) (((x) > 0) ? (x) : (-(x)))
  42. #endif
  43. #define GRAB_MASK (KeyPressMask | ButtonPressMask | ButtonReleaseMask |\
  44. PointerMotionMask)
  45. #define PGRAB_MASK (ButtonPressMask | ButtonReleaseMask |\
  46. PointerMotionMask | PointerMotionHintMask)
  47. #define NOFRZ_GRAB_MASK (KeyPressMask | ButtonPressMask |\
  48. ButtonReleaseMask)
  49. #define NOFRZ_PGRAB_MASK (ButtonPressMask | ButtonReleaseMask)
  50. /*
  51. * include extern functions
  52. */
  53. #include "WmCDInfo.h"
  54. #include "WmCDecor.h"
  55. #include "WmFeedback.h"
  56. #include "WmWinConf.h"
  57. /*
  58. * Global Variables:
  59. */
  60. static int placeX;
  61. static int placeY;
  62. static unsigned int placeWidth;
  63. static unsigned int placeHeight;
  64. static Boolean placeResize;
  65. static Boolean placementDone;
  66. static int placePointerX;
  67. static int placePointerY;
  68. static int placeKeyMultiplier;
  69. static int placeOffsetX;
  70. static int placeOffsetY;
  71. /*************************************<->*************************************
  72. *
  73. * SetupPlacement (pcd)
  74. *
  75. *
  76. * Description:
  77. * -----------
  78. * Perform the initialization for interactive placement
  79. *
  80. *
  81. * Inputs:
  82. * ------
  83. * pcd - pointer to client data
  84. *
  85. * Outputs:
  86. * -------
  87. *
  88. *
  89. * Comments:
  90. * --------
  91. * o sets up global data and puts initial display on the screen
  92. *
  93. *************************************<->***********************************/
  94. void SetupPlacement (ClientData *pcd)
  95. {
  96. int cX, cY, junk;
  97. Window junk_win;
  98. /*
  99. * Restore the state of the last "depressed" frame gadget
  100. */
  101. if (wmGD.gadgetClient && wmGD.gadgetDepressed)
  102. {
  103. PopGadgetOut(wmGD.gadgetClient, wmGD.gadgetDepressed);
  104. }
  105. /* get offset of frame origin from window origin */
  106. placeOffsetX = pcd->clientOffset.x;
  107. placeOffsetY = pcd->clientOffset.y;
  108. XQueryPointer (DISPLAY, ACTIVE_ROOT,
  109. &junk_win, &junk_win,
  110. &cX, &cY, &junk, &junk, (unsigned int *)&junk);
  111. /* convert to frame coordinates */
  112. placePointerX = placeX = cX;
  113. placePointerY = placeY = cY;
  114. placeWidth = pcd->clientWidth;
  115. placeHeight = pcd->clientHeight;
  116. ClientToFrame (pcd, &cX, &cY, &placeWidth, &placeHeight);
  117. /* in "position" mode to start with */
  118. placeResize = FALSE;
  119. wmGD.preMove = FALSE;
  120. /* normal window being dealt with, not icon */
  121. wmGD.movingIcon = FALSE;
  122. if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
  123. {
  124. DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
  125. (FB_SIZE | FB_POSITION), placeResize);
  126. }
  127. /* set up initial visual feedback */
  128. MoveOutline (placeX, placeY, placeWidth, placeHeight);
  129. } /* END OF FUNCTION SetupPlacement */
  130. /*************************************<->*************************************
  131. *
  132. * IsRepeatedKeyEvent (dpy, pEvent, pOldEvent)
  133. *
  134. *
  135. * Description:
  136. * -----------
  137. * Returns TRUE if the event passed in is a repeat of the key event
  138. * indicated in pOldEvent
  139. *
  140. *
  141. * Inputs:
  142. * ------
  143. * dpy - display
  144. * pEvent - pointer to this event
  145. * pOldEvent - pointer to previous event (cast to the correct type)
  146. *
  147. *
  148. * Outputs:
  149. * -------
  150. * IsRepeatedKeyEvent - True if the events are "the same,"
  151. * False otherwise.
  152. *
  153. *
  154. * Comments:
  155. * --------
  156. *
  157. *************************************<->***********************************/
  158. Bool IsRepeatedKeyEvent (Display *dpy, XEvent *pEvent, char *pOldEvent)
  159. {
  160. XEvent *pOld = (XEvent *) pOldEvent;
  161. if ((pEvent->type == KeyPress) && /* key press event */
  162. (pEvent->type == pOld->type) && /* same event type */
  163. (pEvent->xkey.keycode == pOld->xkey.keycode) && /* same key code */
  164. (pEvent->xkey.state == pOld->xkey.state) && /* same modifiers */
  165. (pEvent->xkey.window == pOld->xkey.window) && /* same window */
  166. (pEvent->xkey.root == pOld->xkey.root)) /* same root */
  167. {
  168. return (True);
  169. }
  170. else
  171. {
  172. return (False);
  173. }
  174. }
  175. /*************************************<->*************************************
  176. *
  177. * StartInteractiveSizing (pcd, time)
  178. *
  179. *
  180. * Description:
  181. * -----------
  182. * Switch from "position" mode to "resize" mode
  183. *
  184. *
  185. * Inputs:
  186. * ------
  187. * pcd - pointer to client data
  188. * time - time stamp of event for pointer regrab
  189. *
  190. *
  191. * Outputs:
  192. * -------
  193. *
  194. *
  195. * Comments:
  196. * --------
  197. *
  198. *************************************<->***********************************/
  199. void StartInteractiveSizing (ClientData *pcd, Time time)
  200. {
  201. unsigned int gmask;
  202. /* regrab pointer to change cursor */
  203. gmask = (wmGD.freezeOnConfig)? PGRAB_MASK : NOFRZ_PGRAB_MASK;
  204. XChangeActivePointerGrab (DISPLAY, gmask,
  205. wmGD.sizePlacementCursor, time);
  206. /* put cursor at lower-right corner */
  207. if (wmGD.enableWarp)
  208. {
  209. XWarpPointer (DISPLAY, None, ACTIVE_ROOT, 0, 0, 0, 0,
  210. (int) (placeX+placeWidth-1), (int) (placeY+placeHeight-1));
  211. }
  212. /*
  213. * Don't go into resize mode if resize is turned off.
  214. */
  215. if (pcd->clientFunctions & MWM_FUNC_RESIZE)
  216. {
  217. /* update flags */
  218. placeResize = TRUE;
  219. wmGD.preMove = FALSE;
  220. }
  221. }
  222. /*************************************<->*************************************
  223. *
  224. * HandlePlacementKeyEvent (pcd, pev)
  225. *
  226. *
  227. * Description:
  228. * -----------
  229. * Handle key presses during interactive placement
  230. *
  231. *
  232. * Inputs:
  233. * ------
  234. * pcd - pointer to client data
  235. * pev - pointer to key press event
  236. *
  237. * Outputs:
  238. * -------
  239. *
  240. *
  241. * Comments:
  242. * --------
  243. *
  244. *************************************<->***********************************/
  245. void HandlePlacementKeyEvent (ClientData *pcd, XKeyEvent *pev)
  246. {
  247. XEvent KeyEvent;
  248. KeySym keysym;
  249. Boolean control, valid;
  250. int big_inc;
  251. int tmpX = 0;
  252. int tmpY = 0;
  253. int warpX, warpY, newX, newY;
  254. int keyPlaceX = placeX;
  255. int keyPlaceY = placeY;
  256. unsigned int keyPlaceWidth = placeWidth;
  257. unsigned int keyPlaceHeight = placeHeight;
  258. /* filter out repeating keys */
  259. placeKeyMultiplier = 1;
  260. if (pev->type == KeyPress)
  261. {
  262. while (placeKeyMultiplier <= 10 &&
  263. XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
  264. (char *) pev))
  265. {
  266. placeKeyMultiplier++;
  267. }
  268. }
  269. /* convert event data to useful key data */
  270. keysym = XKeycodeToKeysym (DISPLAY, pev->keycode, 0);
  271. control = (pev->state & ControlMask) != 0;
  272. big_inc = DisplayWidth(DISPLAY, ACTIVE_PSD->screen) / 20;
  273. /* interpret key data */
  274. valid = FALSE;
  275. switch (keysym)
  276. {
  277. case XK_Left:
  278. tmpX = (control) ? (-big_inc) : -1;
  279. valid = TRUE;
  280. break;
  281. case XK_Up:
  282. tmpY = (control) ? (-big_inc) : -1;
  283. valid = TRUE;
  284. break;
  285. case XK_Right:
  286. tmpX = (control) ? (big_inc) : 1;
  287. valid = TRUE;
  288. break;
  289. case XK_Down:
  290. tmpY = (control) ? (big_inc) : 1;
  291. valid = TRUE;
  292. break;
  293. case XK_space:
  294. StartInteractiveSizing(pcd, pev->time);
  295. break;
  296. case XK_Return:
  297. placementDone = TRUE; /* global "done" flag */
  298. break;
  299. default:
  300. break;
  301. }
  302. /* if a valid key was pressed, then react to it */
  303. if (valid) {
  304. tmpX *= placeKeyMultiplier;
  305. tmpY *= placeKeyMultiplier;
  306. if (placeResize)
  307. {
  308. keyPlaceWidth += tmpX; /* change size of outline */
  309. keyPlaceHeight += tmpY;
  310. FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth,
  311. &keyPlaceHeight, placeResize);
  312. warpX = keyPlaceX+keyPlaceWidth-1;
  313. warpY = keyPlaceY+keyPlaceHeight-1;
  314. SetPointerPosition (warpX, warpY, &newX, &newY);
  315. if ((warpX == newX) && (warpY == newY))
  316. {
  317. placeWidth = keyPlaceWidth;
  318. placeHeight = keyPlaceHeight;
  319. }
  320. else
  321. {
  322. placeWidth = newX - keyPlaceX + 1;
  323. placeHeight = newY - keyPlaceY + 1;
  324. }
  325. }
  326. else
  327. {
  328. keyPlaceX += tmpX; /* change position of outline */
  329. keyPlaceY += tmpY;
  330. FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth,
  331. &keyPlaceHeight, placeResize);
  332. warpX = keyPlaceX;
  333. warpY = keyPlaceY;
  334. SetPointerPosition (warpX, warpY, &newX, &newY);
  335. placeX = newX;
  336. placeY = newY;
  337. }
  338. placePointerX = newX;
  339. placePointerY = newY;
  340. }
  341. FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight,
  342. placeResize);
  343. MoveOutline (placeX, placeY, placeWidth, placeHeight);
  344. if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
  345. {
  346. DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
  347. 0, placeResize);
  348. }
  349. } /* END OF FUNCTION HandlePlacementKeyEvent */
  350. /*************************************<->*************************************
  351. *
  352. * HandlePlacementButtonEvent (pev)
  353. *
  354. *
  355. * Description:
  356. * -----------
  357. * XXDescription ...
  358. *
  359. *
  360. * Inputs:
  361. * ------
  362. * pev - pointer to button event
  363. *
  364. * Outputs:
  365. * -------
  366. *
  367. *
  368. * Comments:
  369. * --------
  370. *
  371. *************************************<->***********************************/
  372. void HandlePlacementButtonEvent (XButtonEvent *pev)
  373. {
  374. /*
  375. * Only listen to button 1
  376. */
  377. if (pev->button == 1)
  378. {
  379. /*
  380. * Complete interactive placement on button release
  381. */
  382. if (pev->type == ButtonRelease)
  383. {
  384. placementDone = TRUE; /* global done flag */
  385. }
  386. else if (pev->type == ButtonPress)
  387. {
  388. /*
  389. * Button press, go to pre-resize mode
  390. */
  391. wmGD.preMoveX = pev->x_root;
  392. wmGD.preMoveY = pev->y_root;
  393. wmGD.preMove = TRUE;
  394. }
  395. }
  396. }
  397. /*************************************<->*************************************
  398. *
  399. * HandlePlacementMotionEvent (pcd, pev)
  400. *
  401. *
  402. * Description:
  403. * -----------
  404. * Handles pointer motion events during interactive placement
  405. *
  406. *
  407. * Inputs:
  408. * ------
  409. * pcd - pointer to client data
  410. * pev - pointer to mouse motion event
  411. *
  412. *
  413. * Outputs:
  414. * -------
  415. *
  416. *
  417. * Comments:
  418. * --------
  419. *
  420. *************************************<->***********************************/
  421. void HandlePlacementMotionEvent (ClientData *pcd, XMotionEvent *pev)
  422. {
  423. int diffx, diffy;
  424. /*
  425. * If in pre-resize mode, check for motion crossing threshold before
  426. * switching modes
  427. */
  428. if (wmGD.preMove) {
  429. diffx = pev->x_root - wmGD.preMoveX;
  430. diffy = pev->y_root - wmGD.preMoveY;
  431. if ((ABS(diffx) > wmGD.moveThreshold) ||
  432. (ABS(diffy) > wmGD.moveThreshold))
  433. {
  434. StartInteractiveSizing(pcd, pev->time);
  435. }
  436. return;
  437. }
  438. if (placeResize) {
  439. /*
  440. * Track lower right corner
  441. */
  442. if (pev->x_root > placeX)
  443. placeWidth = pev->x_root - placeX + 1;
  444. if (pev->y_root > placeY)
  445. placeHeight = pev->y_root - placeY + 1;
  446. }
  447. else {
  448. /*
  449. * track window position
  450. */
  451. placeX = pev->x_root;
  452. placeY = pev->y_root;
  453. }
  454. placePointerX = pev->x_root;
  455. placePointerY = pev->y_root;
  456. FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight,
  457. placeResize);
  458. MoveOutline (placeX, placeY, placeWidth, placeHeight);
  459. if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
  460. {
  461. DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
  462. 0, placeResize);
  463. }
  464. } /* END OF FUNCTION HandlePlacementMotionEvent */
  465. /*************************************<->*************************************
  466. *
  467. * DoPlacement (pcd)
  468. *
  469. *
  470. * Description:
  471. * -----------
  472. * Gets window configuration from the user via pointer/keyboard interaction
  473. *
  474. *
  475. * Inputs:
  476. * ------
  477. * pcd - pointer to client data
  478. *
  479. *
  480. * Outputs:
  481. * -------
  482. * pcd - clientX, clientY, clientWidth, and clientHeight members
  483. * could be changed
  484. *
  485. * Comments:
  486. * --------
  487. * We try to be careful only to remove events that we need from the
  488. * event queue while we're in our own event processing loop.
  489. *
  490. *************************************<->***********************************/
  491. void DoPlacement (ClientData *pcd)
  492. {
  493. XEvent event;
  494. /*
  495. * Initialization
  496. */
  497. SetupPlacement (pcd);
  498. /*
  499. * Process events
  500. */
  501. placementDone = FALSE;
  502. while (!placementDone)
  503. {
  504. GetConfigEvent (DISPLAY, ACTIVE_ROOT, GRAB_MASK,
  505. placePointerX, placePointerY, placeX, placeY,
  506. placeWidth, placeHeight, &event);
  507. switch (event.type) {
  508. case KeyPress:
  509. HandlePlacementKeyEvent(pcd, (XKeyEvent *)&event);
  510. break;
  511. case ButtonPress:
  512. HandlePlacementButtonEvent((XButtonEvent *)&event);
  513. break;
  514. case ButtonRelease:
  515. HandlePlacementButtonEvent((XButtonEvent *)&event);
  516. break;
  517. case MotionNotify:
  518. HandlePlacementMotionEvent(pcd, (XMotionEvent *)&event);
  519. break;
  520. }
  521. }
  522. /* copy back the configuration information */
  523. pcd->clientX = placeX + placeOffsetX;
  524. pcd->clientY = placeY + placeOffsetY;
  525. pcd->clientWidth = placeWidth - 2*placeOffsetX;
  526. pcd->clientHeight = placeHeight - placeOffsetX - placeOffsetY;
  527. /* clean up */
  528. MoveOutline (0,0,0,0);
  529. HideFeedbackWindow(pcd->pSD);
  530. } /* END OF FUNCTION DoPlacement */
  531. /*************************************<->*************************************
  532. *
  533. * PlaceWindowInteractively(pcd)
  534. *
  535. *
  536. * Description:
  537. * -----------
  538. * Gets the clients size and position information interactively from the
  539. * user.
  540. *
  541. *
  542. * Inputs:
  543. * ------
  544. * pcd - pointer to client data
  545. *
  546. *
  547. * Outputs:
  548. * -------
  549. *
  550. *
  551. * Comments:
  552. * --------
  553. *
  554. *************************************<->***********************************/
  555. void PlaceWindowInteractively (ClientData *pcd)
  556. {
  557. unsigned int gmask;
  558. gmask = (wmGD.freezeOnConfig)? PGRAB_MASK : NOFRZ_PGRAB_MASK;
  559. /*
  560. * Return if config is in progress or if grabs fail
  561. */
  562. if (!DoGrabs (ACTIVE_ROOT, wmGD.movePlacementCursor,
  563. gmask, CurrentTime, pcd, True))
  564. {
  565. return;
  566. }
  567. /*
  568. * Get the size and position of the window from the user.
  569. * Do our own event processing until a button-up event occurs
  570. */
  571. DoPlacement(pcd);
  572. /*
  573. * Finish up and return the data
  574. */
  575. UndoGrabs();
  576. wmGD.preMove = FALSE;
  577. }