/* * CDE - Common Desktop Environment * * (c) Copyright 1993-2012 The Open Group * (c) Copyright 2012-2022 CDE Project contributors, see * CONTRIBUTORS for details * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include
#include
#include "WmGlobal.h" #include "WmCDecor.h" #include "WmError.h" #include "WmHelp.h" #include "WmIDecor.h" #include "WmInstantTitle.h" #include "WmPanelP.h" #include "WmProperty.h" #include "WmWinList.h" #include "WmWrkspace.h" extern XtPointer _XmStringUngenerate(XmString, XmStringTag, XmTextType, XmTextType); static void InstantTitleGetTitle(PtrInstantTitleData pITD) { String value; Widget textFieldW = pITD->textFieldW; ClientData *pCD = pITD->pCDforClient; XmString title = pITD->contextForClient == F_CONTEXT_ICON ? ICON_DISPLAY_TITLE(pCD) : CLIENT_DISPLAY_TITLE(pCD); if (!title) return; value = _XmStringUngenerate(title, NULL, XmCHARSET_TEXT, XmCHARSET_TEXT); if (!value) return; XtVaSetValues(textFieldW, XmNvalue, value, NULL); XtFree(value); XtVaSetValues(textFieldW, XmNcursorPosition, XmTextFieldGetLastPosition(textFieldW), NULL); } static void InstantTitleSetTitle(PtrInstantTitleData pITD) { char *str = XmTextFieldGetString(pITD->textFieldW); ClientData *pCD = pITD->pCDforClient; Context context = pITD->contextForClient; XmString *title = &pCD->instantTitle; Window client = pCD->client; Atom name = wmGD.xa__NET_WM_VISIBLE_NAME; Atom iconName = wmGD.xa__NET_WM_VISIBLE_ICON_NAME; if (*title) XmStringFree(*title); _DtStripSpaces(str); if (str[0]) { *title = XmStringCreateLocalized(str); SetUtf8String (DISPLAY, client, name, str); SetUtf8String (DISPLAY, client, iconName, str); } else { *title = NULL; XDeleteProperty(DISPLAY, client, name); XDeleteProperty(DISPLAY, client, iconName); } XtFree(str); if (context == F_CONTEXT_ICON || pCD->pSD->useIconBox) RedisplayIconTitle(pCD); if (context != F_CONTEXT_ICON) DrawWindowTitle(pCD, True); } /** * @brief Hides the instant title dialog. * * @param pClientData */ void InstantTitleHideDialog(ClientData *pClientData) { PtrInstantTitleData pITD = &pClientData->pSD->instantTitleData; if (pITD->widgetsInitialized && pITD->pCDforClient == pClientData) XtUnmanageChild(pITD->dialogBoxW); } static void InstantTitleButtonCB(Widget w, XtPointer client_data, XtPointer call_data) { PtrInstantTitleData pITD = client_data; DtDialogBoxCallbackStruct *cb = call_data; switch (cb->button_position) { case 1: InstantTitleSetTitle(pITD); case 2: InstantTitleHideDialog(pITD->pCDforClient); break; case 3: XtCallCallbacks(pITD->dialogBoxW, XmNhelpCallback, NULL); break; default: break; } } static void InstantTitleWorkspaceModifyCB(Widget w, Atom atom_name, int type, XtPointer client_data) { PtrInstantTitleData pITD = client_data; ClientData *pCD = pITD->pCDforClient; if (type == DtWSM_REASON_CURRENT && pITD->contextForClient == F_CONTEXT_ICON && XtIsManaged(pITD->dialogBoxW) && ClientInWorkspace(ACTIVE_WS, pCD)) InstantTitleShowDialog(pCD); } static Boolean InstantTitleMakeDialog(PtrInstantTitleData pITD) { Cardinal n; Arg args[10]; XmString buttonStrings[3]; Widget dialogShellW, dialogBoxW, formW, cancelW, textFieldW; Boolean *widgetsInitialized = &pITD->widgetsInitialized; if (*widgetsInitialized) return True; n = 0; XtSetArg(args[n], XmNallowShellResize, True); ++n; XtSetArg(args[n], XmNmwmFunctions, MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE); ++n; dialogShellW = pITD->dialogShellW = XtCreatePopupShell( "instantTitleDialogShell", xmDialogShellWidgetClass, pITD->pCDforClient->pSD->screenTopLevelW1, args, n); if (!dialogShellW) goto err; if (!DtWsmAddWorkspaceModifiedCallback(dialogShellW, InstantTitleWorkspaceModifyCB, pITD)) goto err; buttonStrings[0] = XmStringCreateLocalized((char *)_DtOkString); buttonStrings[1] = XmStringCreateLocalized((char *)_DtCancelString); buttonStrings[2] = XmStringCreateLocalized((char *)_DtHelpString); n = 0; XtSetArg(args[n], XmNallowOverlap, False); ++n; XtSetArg(args[n], XmNdefaultPosition, False); ++n; XtSetArg(args[n], XmNbuttonCount, 3); ++n; XtSetArg(args[n], XmNbuttonLabelStrings, buttonStrings); ++n; dialogBoxW = pITD->dialogBoxW = _DtCreateDialogBox(dialogShellW, "instantTitleDialogBox", args, n); XmStringFree(buttonStrings[0]); XmStringFree(buttonStrings[1]); XmStringFree(buttonStrings[2]); if (!dialogBoxW) goto err; XtAddCallback(dialogBoxW, XmNcallback, InstantTitleButtonCB, pITD); XtAddCallback(dialogBoxW, XmNhelpCallback, WmDtWmTopicHelpCB, WM_DT_WINDOWRENAME_TOPIC); cancelW = _DtDialogBoxGetButton(dialogBoxW, 2); if (!cancelW) goto err; n = 0; XtSetArg(args[n], XmNautoUnmanage, False); ++n; XtSetArg(args[n], XmNcancelButton, cancelW); ++n; XtSetValues (dialogBoxW, args, n); formW = pITD->formW = XmCreateForm(dialogBoxW, "instantTitleForm", NULL, 0); if (!formW) goto err; n = 0; XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); ++n; XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); ++n; XtSetArg(args[n], XmNmaxLength, FILENAME_MAX); ++n; textFieldW = pITD->textFieldW = XmCreateTextField(formW, "instantTitleTextField", args, n); if (!textFieldW) goto err; XtManageChild(dialogShellW); XtManageChild(dialogBoxW); XtManageChild(formW); XtManageChild(cancelW); XtManageChild(textFieldW); DtWsmRemoveWorkspaceFunctions(DISPLAY1, XtWindow(dialogShellW)); *widgetsInitialized = True; return True; err: if (dialogShellW) { XtDestroyWidget(dialogShellW); *widgetsInitialized = False; } Warning(GETMESSAGE(88, 1, "1 Unable to create instant title dialog.")); return False; } static void InstantTitleSetPosition(PtrInstantTitleData pITD) { int x, y; Dimension height; Cardinal n; Arg args[10]; XFontStruct *font; Window windowGroup; Widget dialogShellW = pITD->dialogShellW; Context context = pITD->contextForClient; ClientData *pCD = pITD->pCDforClient; WmScreenData *pSD = pCD->pSD; XtVaGetValues(dialogShellW, XmNheight, &height, NULL); if (wmGD.positionIsFrame) { if (pSD->decoupleTitleAppearance) font = pSD->clientTitleAppearance.font; else font = pSD->clientAppearance.font; height += TEXT_HEIGHT(font) + (2 * pSD->frameBorderWidth); } GetSystemMenuPosition(pCD, &x, &y, height, context); if (context == F_CONTEXT_ICON) { if (pSD->useIconBox && P_ICON_BOX(pCD)) windowGroup = P_ICON_BOX(pCD)->pCD_iconBox->client; else windowGroup = XtUnspecifiedWindowGroup; } else { windowGroup = pCD->client; } n = 0; XtSetArg(args[n], XmNx, x); ++n; XtSetArg(args[n], XmNy, y); ++n; XtSetArg(args[n], XmNtransientFor, NULL); ++n; XtSetArg(args[n], XmNwindowGroup, windowGroup); ++n; XtSetValues(dialogShellW, args, n); } /** * @brief Shows the instant title dialog. * * @param pClientData * @param context */ void InstantTitleShowDialog(ClientData *pClientData) { Widget dialogBoxW, textFieldW; Context context; ClientData *pCD = pClientData->transientLeader ? FindTransientTreeLeader(pClientData) : pClientData; WmScreenData *pSD = pCD->pSD; PtrInstantTitleData pITD = &pSD->instantTitleData; switch (pCD->clientState) { case MINIMIZED_STATE: context = F_CONTEXT_ICON; break; case NORMAL_STATE: case MAXIMIZED_STATE: context = F_CONTEXT_WINDOW; break; default: return; } pITD->pCDforClient = pCD; pITD->contextForClient = context; if (!InstantTitleMakeDialog(pITD)) return; InstantTitleGetTitle(pITD); InstantTitleSetPosition(pITD); dialogBoxW = pITD->dialogBoxW; XtUnmanageChild(dialogBoxW); XtManageChild(dialogBoxW); textFieldW = pITD->textFieldW; XmProcessTraversal(textFieldW, XmTRAVERSE_CURRENT); XmTextSetSelection(textFieldW, 0, XmTextGetLastPosition(textFieldW), CurrentTime); }