WmInstantTitle.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * (c) Copyright 1993-2012 The Open Group
  5. * (c) Copyright 2012-2022 CDE Project contributors, see
  6. * CONTRIBUTORS for details
  7. *
  8. * These libraries and programs are free software; you can
  9. * redistribute them and/or modify them under the terms of the GNU
  10. * Lesser General Public License as published by the Free Software
  11. * Foundation; either version 2 of the License, or (at your option)
  12. * any later version.
  13. *
  14. * These libraries and programs are distributed in the hope that
  15. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  16. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  17. * PURPOSE. See the GNU Lesser General Public License for more
  18. * details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with these libraries and programs; if not, write
  22. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  23. * Floor, Boston, MA 02110-1301 USA
  24. */
  25. #include <Xm/DialogS.h>
  26. #include <Xm/Form.h>
  27. #include <Xm/Text.h>
  28. #include <Xm/TextF.h>
  29. #include <Dt/DialogBox.h>
  30. #include <Dt/SharedProcs.h>
  31. #include "WmGlobal.h"
  32. #include "WmCDecor.h"
  33. #include "WmError.h"
  34. #include "WmHelp.h"
  35. #include "WmIDecor.h"
  36. #include "WmInstantTitle.h"
  37. #include "WmPanelP.h"
  38. #include "WmProperty.h"
  39. #include "WmWinList.h"
  40. #include "WmWrkspace.h"
  41. extern XtPointer _XmStringUngenerate(XmString, XmStringTag,
  42. XmTextType, XmTextType);
  43. static void InstantTitleGetTitle(PtrInstantTitleData pITD) {
  44. String value;
  45. Widget textFieldW = pITD->textFieldW;
  46. ClientData *pCD = pITD->pCDforClient;
  47. XmString title = pITD->contextForClient == F_CONTEXT_ICON ?
  48. ICON_DISPLAY_TITLE(pCD) : CLIENT_DISPLAY_TITLE(pCD);
  49. if (!title) return;
  50. value = _XmStringUngenerate(title, NULL, XmCHARSET_TEXT, XmCHARSET_TEXT);
  51. if (!value) return;
  52. XtVaSetValues(textFieldW, XmNvalue, value, NULL);
  53. XtFree(value);
  54. XtVaSetValues(textFieldW, XmNcursorPosition,
  55. XmTextFieldGetLastPosition(textFieldW), NULL);
  56. }
  57. static void InstantTitleSetTitle(PtrInstantTitleData pITD) {
  58. char *str = XmTextFieldGetString(pITD->textFieldW);
  59. ClientData *pCD = pITD->pCDforClient;
  60. Context context = pITD->contextForClient;
  61. XmString *title = &pCD->instantTitle;
  62. Window client = pCD->client;
  63. Atom name = wmGD.xa__NET_WM_VISIBLE_NAME;
  64. Atom iconName = wmGD.xa__NET_WM_VISIBLE_ICON_NAME;
  65. if (*title) XmStringFree(*title);
  66. _DtStripSpaces(str);
  67. if (str[0]) {
  68. *title = XmStringCreateLocalized(str);
  69. SetUtf8String (DISPLAY, client, name, str);
  70. SetUtf8String (DISPLAY, client, iconName, str);
  71. }
  72. else {
  73. *title = NULL;
  74. XDeleteProperty(DISPLAY, client, name);
  75. XDeleteProperty(DISPLAY, client, iconName);
  76. }
  77. XtFree(str);
  78. if (context == F_CONTEXT_ICON || pCD->pSD->useIconBox)
  79. RedisplayIconTitle(pCD);
  80. if (context != F_CONTEXT_ICON) DrawWindowTitle(pCD, True);
  81. }
  82. /**
  83. * @brief Hides the instant title dialog.
  84. *
  85. * @param pClientData
  86. */
  87. void InstantTitleHideDialog(ClientData *pClientData) {
  88. PtrInstantTitleData pITD = &pClientData->pSD->instantTitleData;
  89. if (pITD->widgetsInitialized && pITD->pCDforClient == pClientData)
  90. XtUnmanageChild(pITD->dialogBoxW);
  91. }
  92. static void InstantTitleButtonCB(Widget w, XtPointer client_data,
  93. XtPointer call_data)
  94. {
  95. PtrInstantTitleData pITD = client_data;
  96. DtDialogBoxCallbackStruct *cb = call_data;
  97. switch (cb->button_position) {
  98. case 1:
  99. InstantTitleSetTitle(pITD);
  100. case 2:
  101. InstantTitleHideDialog(pITD->pCDforClient);
  102. break;
  103. case 3:
  104. XtCallCallbacks(pITD->dialogBoxW, XmNhelpCallback, NULL);
  105. break;
  106. default:
  107. break;
  108. }
  109. }
  110. static void InstantTitleWorkspaceModifyCB(Widget w, Atom atom_name, int type,
  111. XtPointer client_data)
  112. {
  113. PtrInstantTitleData pITD = client_data;
  114. ClientData *pCD = pITD->pCDforClient;
  115. if (type == DtWSM_REASON_CURRENT &&
  116. pITD->contextForClient == F_CONTEXT_ICON &&
  117. XtIsManaged(pITD->dialogBoxW) && ClientInWorkspace(ACTIVE_WS, pCD))
  118. InstantTitleShowDialog(pCD);
  119. }
  120. static Boolean InstantTitleMakeDialog(PtrInstantTitleData pITD) {
  121. Cardinal n;
  122. Arg args[10];
  123. XmString buttonStrings[3];
  124. Widget dialogShellW, dialogBoxW, formW, cancelW, textFieldW;
  125. Boolean *widgetsInitialized = &pITD->widgetsInitialized;
  126. if (*widgetsInitialized) return True;
  127. n = 0;
  128. XtSetArg(args[n], XmNallowShellResize, True); ++n;
  129. XtSetArg(args[n], XmNmwmFunctions,
  130. MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE); ++n;
  131. dialogShellW = pITD->dialogShellW = XtCreatePopupShell(
  132. "instantTitleDialogShell", xmDialogShellWidgetClass,
  133. pITD->pCDforClient->pSD->screenTopLevelW1, args, n);
  134. if (!dialogShellW) goto err;
  135. if (!DtWsmAddWorkspaceModifiedCallback(dialogShellW,
  136. InstantTitleWorkspaceModifyCB, pITD)) goto err;
  137. buttonStrings[0] = XmStringCreateLocalized((char *)_DtOkString);
  138. buttonStrings[1] = XmStringCreateLocalized((char *)_DtCancelString);
  139. buttonStrings[2] = XmStringCreateLocalized((char *)_DtHelpString);
  140. n = 0;
  141. XtSetArg(args[n], XmNallowOverlap, False); ++n;
  142. XtSetArg(args[n], XmNdefaultPosition, False); ++n;
  143. XtSetArg(args[n], XmNbuttonCount, 3); ++n;
  144. XtSetArg(args[n], XmNbuttonLabelStrings, buttonStrings); ++n;
  145. dialogBoxW = pITD->dialogBoxW = _DtCreateDialogBox(dialogShellW,
  146. "instantTitleDialogBox", args, n);
  147. XmStringFree(buttonStrings[0]);
  148. XmStringFree(buttonStrings[1]);
  149. XmStringFree(buttonStrings[2]);
  150. if (!dialogBoxW) goto err;
  151. XtAddCallback(dialogBoxW, XmNcallback, InstantTitleButtonCB, pITD);
  152. XtAddCallback(dialogBoxW, XmNhelpCallback, WmDtWmTopicHelpCB,
  153. WM_DT_WINDOWRENAME_TOPIC);
  154. cancelW = _DtDialogBoxGetButton(dialogBoxW, 2);
  155. if (!cancelW) goto err;
  156. n = 0;
  157. XtSetArg(args[n], XmNautoUnmanage, False); ++n;
  158. XtSetArg(args[n], XmNcancelButton, cancelW); ++n;
  159. XtSetValues (dialogBoxW, args, n);
  160. formW = pITD->formW = XmCreateForm(dialogBoxW, "instantTitleForm", NULL, 0);
  161. if (!formW) goto err;
  162. n = 0;
  163. XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); ++n;
  164. XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
  165. XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
  166. XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); ++n;
  167. XtSetArg(args[n], XmNmaxLength, FILENAME_MAX); ++n;
  168. textFieldW = pITD->textFieldW = XmCreateTextField(formW,
  169. "instantTitleTextField", args, n);
  170. if (!textFieldW) goto err;
  171. XtManageChild(dialogShellW);
  172. XtManageChild(dialogBoxW);
  173. XtManageChild(formW);
  174. XtManageChild(cancelW);
  175. XtManageChild(textFieldW);
  176. DtWsmRemoveWorkspaceFunctions(DISPLAY1, XtWindow(dialogShellW));
  177. *widgetsInitialized = True;
  178. return True;
  179. err:
  180. if (dialogShellW) {
  181. XtDestroyWidget(dialogShellW);
  182. *widgetsInitialized = False;
  183. }
  184. Warning(GETMESSAGE(88, 1, "1 Unable to create instant title dialog."));
  185. return False;
  186. }
  187. static void InstantTitleSetPosition(PtrInstantTitleData pITD) {
  188. int x, y;
  189. Dimension height;
  190. Cardinal n;
  191. Arg args[10];
  192. XFontStruct *font;
  193. Window windowGroup;
  194. Widget dialogShellW = pITD->dialogShellW;
  195. Context context = pITD->contextForClient;
  196. ClientData *pCD = pITD->pCDforClient;
  197. WmScreenData *pSD = pCD->pSD;
  198. XtVaGetValues(dialogShellW, XmNheight, &height, NULL);
  199. if (wmGD.positionIsFrame) {
  200. if (pSD->decoupleTitleAppearance)
  201. font = pSD->clientTitleAppearance.font;
  202. else
  203. font = pSD->clientAppearance.font;
  204. height += TEXT_HEIGHT(font) + (2 * pSD->frameBorderWidth);
  205. }
  206. GetSystemMenuPosition(pCD, &x, &y, height, context);
  207. if (context == F_CONTEXT_ICON) {
  208. if (pSD->useIconBox && P_ICON_BOX(pCD))
  209. windowGroup = P_ICON_BOX(pCD)->pCD_iconBox->client;
  210. else
  211. windowGroup = XtUnspecifiedWindowGroup;
  212. }
  213. else {
  214. windowGroup = pCD->client;
  215. }
  216. n = 0;
  217. XtSetArg(args[n], XmNx, x); ++n;
  218. XtSetArg(args[n], XmNy, y); ++n;
  219. XtSetArg(args[n], XmNtransientFor, NULL); ++n;
  220. XtSetArg(args[n], XmNwindowGroup, windowGroup); ++n;
  221. XtSetValues(dialogShellW, args, n);
  222. }
  223. /**
  224. * @brief Shows the instant title dialog.
  225. *
  226. * @param pClientData
  227. * @param context
  228. */
  229. void InstantTitleShowDialog(ClientData *pClientData) {
  230. Widget dialogBoxW, textFieldW;
  231. Context context;
  232. ClientData *pCD = pClientData->transientLeader ?
  233. FindTransientTreeLeader(pClientData) : pClientData;
  234. WmScreenData *pSD = pCD->pSD;
  235. PtrInstantTitleData pITD = &pSD->instantTitleData;
  236. switch (pCD->clientState) {
  237. case MINIMIZED_STATE:
  238. context = F_CONTEXT_ICON;
  239. break;
  240. case NORMAL_STATE:
  241. case MAXIMIZED_STATE:
  242. context = F_CONTEXT_WINDOW;
  243. break;
  244. default:
  245. return;
  246. }
  247. pITD->pCDforClient = pCD;
  248. pITD->contextForClient = context;
  249. if (!InstantTitleMakeDialog(pITD)) return;
  250. InstantTitleGetTitle(pITD);
  251. InstantTitleSetPosition(pITD);
  252. dialogBoxW = pITD->dialogBoxW;
  253. XtUnmanageChild(dialogBoxW);
  254. XtManageChild(dialogBoxW);
  255. textFieldW = pITD->textFieldW;
  256. XmProcessTraversal(textFieldW, XmTRAVERSE_CURRENT);
  257. XmTextSetSelection(textFieldW, 0, XmTextGetLastPosition(textFieldW),
  258. CurrentTime);
  259. }