2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
31 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
37 #include "WmResNames.h"
39 #define MWM_NEED_TIME16
43 #include <X11/Shell.h>
45 #include <Xm/DialogS.h>
46 #include <Xm/BulletinB.h>
47 #include <Xm/MessageB.h>
49 #define MOVE_OUTLINE_WIDTH 2
50 #define FEEDBACK_BEVEL 2
52 #define DEFAULT_POSITION_STRING "(0000x0000)"
54 #define CB_HIGHLIGHT_THICKNESS 3
57 * include extern functions
59 #include "WmFeedback.h"
60 #include "WmFunction.h"
61 #include "WmGraphics.h"
62 #include "WmPanelP.h" /* for typedef in WmManage.h */
64 #include "WmColormap.h"
71 static Cursor waitCursor = (Cursor)0L;
73 /* see WmGlobal.h for index defines: */
75 #ifndef NO_MESSAGE_CATALOG
76 static char *confirm_mesg[4] = {"Switch to Default Behavior?",
77 "Switch to Custom Behavior?",
89 * catgets returns a pointer to an area that is over written
90 * on each call to catgets.
93 tmpString = ((char *)GETMESSAGE(22, 12, "Switch to Default Behavior?"));
94 if ((confirm_mesg[0] =
95 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
97 Warning (((char *)GETMESSAGE(22, 2, "Insufficient memory for local message string")));
98 confirm_mesg[0] = "Switch to Default Behavior?";
102 strcpy(confirm_mesg[0], tmpString);
105 tmpString = ((char *)GETMESSAGE(22, 13, "Switch to Custom Behavior?"));
106 if ((confirm_mesg[1] =
107 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
109 Warning (((char *)GETMESSAGE(22, 2, "Insufficient memory for local message string")));
110 confirm_mesg[1] = "Switch to Custom Behavior?";
114 strcpy(confirm_mesg[1], tmpString);
119 tmpString = ((char *)GETMESSAGE(22, 3, "Restart Mwm?"));
123 tmpString = ((char *)GETMESSAGE(22, 10, "Restart Workspace Manager?"));
125 if ((confirm_mesg[2] =
126 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
128 Warning (((char *)GETMESSAGE(22, 5, "Insufficient memory for local message string")));
131 confirm_mesg[2] = "Restart Mwm?";
135 confirm_mesg[2] = "Restart Workspace Manager?";
140 strcpy(confirm_mesg[2], tmpString);
147 tmpString = ((char *)GETMESSAGE(22, 6, "QUIT Mwm?"));
153 tmpString = ((char *)GETMESSAGE(22, 9, "Log out?"));
157 tmpString = ((char *)GETMESSAGE(22, 11, "QUIT Workspace Manager?"));
161 if ((confirm_mesg[3] =
162 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
164 Warning (((char *)GETMESSAGE(22, 8, "Insufficient memory for local message string")));
167 confirm_mesg[3] = "QUIT Mwm?";
172 confirm_mesg[3] = "Log out?";
176 confirm_mesg[3] = "QUIT Workspace Manager?";
181 strcpy(confirm_mesg[3], tmpString);
187 static char *confirm_mesg[4] = {"Toggle to Default Behavior?",
188 "Toggle to Custom Behavior?",
193 static char *confirm_widget[4] = {"confirmDefaultBehavior",
194 "confirmCustomBehavior",
199 typedef void (*ConfirmFunc)(Boolean);
200 static ConfirmFunc confirm_func[4] = {Do_Set_Behavior,
206 /*************************************<->*************************************
208 * ShowFeedbackWindow(pSD, x, y, width, height, style)
213 * Pop up the window for moving and sizing feedback
218 * pSD - pointer to screen data
219 * x - initial x-value
220 * y - initial y-value
221 * width - initial width value
222 * height - initial height value
223 * style - show size, position, or both
232 *************************************<->***********************************/
233 void ShowFeedbackWindow (WmScreenData *pSD, int x, int y, unsigned int width, unsigned int height, unsigned long style)
235 unsigned long mask = 0;
236 XSetWindowAttributes win_attribs;
237 XWindowChanges win_changes;
238 int direction, ascent, descent;
239 XCharStruct xcsLocation;
243 if ( (pSD->fbStyle = style) == FB_OFF)
248 pSD->fbLastWidth = width;
249 pSD->fbLastHeight = height;
252 * Derive the size and position of the window from the text extents
253 * Set starting position of each string
255 XTextExtents(pSD->feedbackAppearance.font, DEFAULT_POSITION_STRING,
256 strlen(DEFAULT_POSITION_STRING), &direction, &ascent,
257 &descent, &xcsLocation);
259 pSD->fbWinWidth = xcsLocation.width + 4*FEEDBACK_BEVEL;
261 switch (pSD->fbStyle)
264 pSD->fbSizeY = 2*FEEDBACK_BEVEL + ascent;
265 pSD->fbWinHeight = (ascent + descent) + 4*FEEDBACK_BEVEL;
269 pSD->fbLocY = 2*FEEDBACK_BEVEL + ascent;
270 pSD->fbWinHeight = (ascent + descent) + 4*FEEDBACK_BEVEL;
274 case (FB_SIZE | FB_POSITION):
275 pSD->fbLocY = 2*FEEDBACK_BEVEL + ascent;
276 pSD->fbSizeY = pSD->fbLocY + ascent + descent;
277 pSD->fbWinHeight = 2*(ascent + descent) + 4*FEEDBACK_BEVEL;
281 if (pSD->feedbackGeometry) /* set by user */
283 unsigned int junkWidth, junkHeight;
285 mask = XParseGeometry(pSD->feedbackGeometry, &tmpX, &tmpY,
286 &junkWidth, &junkHeight);
289 if (mask & (XValue|YValue))
291 winX = (mask & XNegative) ?
292 DisplayWidth(DISPLAY, pSD->screen) + tmpX - pSD->fbWinWidth : tmpX;
293 winY = (mask & YNegative) ?
294 DisplayHeight(DISPLAY, pSD->screen) + tmpY -pSD->fbWinHeight : tmpY;
298 winX = (DisplayWidth(DISPLAY, pSD->screen) - pSD->fbWinWidth)/2;
299 winY = (DisplayHeight(DISPLAY, pSD->screen) -pSD->fbWinHeight)/2;
303 * Put new text into the feedback strings
305 UpdateFeedbackText (pSD, x, y, width, height);
308 * bevel the window border for a 3-D look
310 if ( (pSD->fbTop && pSD->fbBottom) ||
311 ((pSD->fbTop = AllocateRList((unsigned)2*FEEDBACK_BEVEL)) &&
312 (pSD->fbBottom = AllocateRList((unsigned)2*FEEDBACK_BEVEL))) )
314 pSD->fbTop->used = 0;
315 pSD->fbBottom->used = 0;
316 BevelRectangle (pSD->fbTop,
319 pSD->fbWinWidth, pSD->fbWinHeight,
320 FEEDBACK_BEVEL, FEEDBACK_BEVEL,
321 FEEDBACK_BEVEL, FEEDBACK_BEVEL);
325 * Create window if not yet created, otherwise fix size and position
328 if (!pSD->feedbackWin)
335 mask = CWEventMask | CWOverrideRedirect | CWSaveUnder;
336 win_attribs.event_mask = ExposureMask;
337 win_attribs.override_redirect = TRUE;
338 win_attribs.save_under = TRUE;
341 * Use background pixmap if one is specified, otherwise set the
342 * appropriate background color.
345 if (pSD->feedbackAppearance.backgroundPixmap)
347 mask |= CWBackPixmap;
348 win_attribs.background_pixmap =
349 pSD->feedbackAppearance.backgroundPixmap;
354 win_attribs.background_pixel =
355 pSD->feedbackAppearance.background;
358 pSD->feedbackWin = XCreateWindow (DISPLAY, pSD->rootWindow,
363 InputOutput, CopyFromParent,
368 win_changes.x = winX;
369 win_changes.y = winY;
370 win_changes.width = pSD->fbWinWidth;
371 win_changes.height = pSD->fbWinHeight;
372 win_changes.stack_mode = Above;
374 mask = CWX | CWY | CWWidth | CWHeight | CWStackMode;
376 XConfigureWindow(DISPLAY, pSD->feedbackWin, (unsigned int) mask,
382 * Make the feedback window visible (map it)
385 if (pSD && pSD->feedbackWin)
387 /* Make sure the feedback window doesn't get buried */
388 XRaiseWindow(DISPLAY, pSD->feedbackWin);
389 XMapWindow (DISPLAY, pSD->feedbackWin);
390 PaintFeedbackWindow(pSD);
393 } /* END OF FUNCTION ShowFeedbackWindow */
397 /*************************************<->*************************************
399 * PaintFeedbackWindow(pSD)
404 * Repaints the feedback window in response to exposure events
409 * pSD - pointer to screen data
417 *************************************<->***********************************/
418 void PaintFeedbackWindow (WmScreenData *pSD)
420 if (pSD->feedbackWin)
425 if (pSD->fbTop && pSD->fbTop->used > 0)
427 XFillRectangles (DISPLAY, pSD->feedbackWin,
428 pSD->feedbackAppearance.inactiveTopShadowGC,
429 pSD->fbTop->prect, pSD->fbTop->used);
431 if (pSD->fbBottom && pSD->fbBottom->used > 0)
433 XFillRectangles (DISPLAY, pSD->feedbackWin,
434 pSD->feedbackAppearance.inactiveBottomShadowGC,
435 pSD->fbBottom->prect,
436 pSD->fbBottom->used);
442 XClearArea (DISPLAY, pSD->feedbackWin,
443 FEEDBACK_BEVEL, FEEDBACK_BEVEL,
444 pSD->fbWinWidth-2*FEEDBACK_BEVEL,
445 pSD->fbWinHeight-2*FEEDBACK_BEVEL,
451 if (pSD->fbStyle & FB_POSITION)
453 WmDrawString (DISPLAY, pSD->feedbackWin,
454 pSD->feedbackAppearance.inactiveGC,
455 pSD->fbLocX, pSD->fbLocY,
456 pSD->fbLocation, strlen(pSD->fbLocation));
458 if (pSD->fbStyle & FB_SIZE)
460 WmDrawString (DISPLAY, pSD->feedbackWin,
461 pSD->feedbackAppearance.inactiveGC,
462 pSD->fbSizeX, pSD->fbSizeY,
463 pSD->fbSize, strlen(pSD->fbSize));
470 /*************************************<->*************************************
472 * HideFeedbackWindow (pSD)
477 * Hide the feedback window
482 * pDS - pointer to screen data
491 *************************************<->***********************************/
492 void HideFeedbackWindow (WmScreenData *pSD)
494 if (pSD->feedbackWin)
496 XUnmapWindow (DISPLAY, pSD->feedbackWin);
498 ForceColormapFocus (ACTIVE_PSD, ACTIVE_PSD->colormapFocus);
501 pSD->fbStyle = FB_OFF;
507 /*************************************<->*************************************
509 * UpdateFeedbackInfo (pSD, x, y, width, height)
514 * Update the information in the feedback window
519 * pSD - pointer to screen info
522 * width - width value
523 * height - height value
533 *************************************<->***********************************/
534 void UpdateFeedbackInfo (WmScreenData *pSD, int x, int y, unsigned int width, unsigned int height)
537 * Currently the feedback window must always be redrawn to (potentially)
538 * repair damage done by moving the configuration outline. The feedback
539 * repainting generally only needs to be done when the information
540 * changes or the feedback window is actually overwritten by the
541 * configuration outline.
545 /* only update if something changed */
546 if (((pSD->fbStyle & FB_POSITION) &&
547 ((pSD->fbLastX != x) || (pSD->fbLastY != y))) ||
548 ((pSD->fbStyle & FB_SIZE) &&
549 ((pSD->fbLastWidth != width) || (pSD->fbLastHeight != height))))
554 pSD->fbLastWidth = width;
555 pSD->fbLastHeight = height;
557 UpdateFeedbackText (pSD, x, y, width, height);
559 PaintFeedbackWindow(pSD);
566 /*************************************<->*************************************
568 * UpdateFeedbackText (pSD, x, y, width, height)
573 * Update the information in the feedback strings
578 * pSD - pointer to screen data
581 * width - width value
582 * height - height value
592 *************************************<->***********************************/
593 void UpdateFeedbackText (WmScreenData *pSD, int x, int y, unsigned int width, unsigned int height)
595 int direction, ascent, descent;
598 if (pSD->fbStyle & FB_POSITION)
600 sprintf (pSD->fbLocation, "(%4d,%-4d)", x, y);
601 XTextExtents(pSD->feedbackAppearance.font, pSD->fbLocation,
602 strlen(pSD->fbLocation), &direction, &ascent,
604 pSD->fbLocX = (pSD->fbWinWidth - xcs.width)/2;
607 if (pSD->fbStyle & FB_SIZE)
609 sprintf (pSD->fbSize, "%4dx%-4d", width, height);
610 XTextExtents(pSD->feedbackAppearance.font, pSD->fbSize,
611 strlen(pSD->fbSize), &direction, &ascent,
613 pSD->fbSizeX = (pSD->fbWinWidth - xcs.width)/2;
619 /*************************************<->*************************************
622 * OkCB (w, client_data, call_data)
627 * QuestionBox Ok callback.
644 *************************************<->***********************************/
646 static void OkCB (Widget w, caddr_t client_data, caddr_t call_data)
650 confirm_func[((WmScreenData *)client_data)->actionNbr] (False);
652 wmGD.confirmDialogMapped = False;
654 } /* END OF FUNCTION OkCB */
657 /*************************************<->*************************************
660 * CancelCB (w, client_data, call_data)
665 * QuestionBox Cancel callback.
682 *************************************<->***********************************/
684 static void CancelCB (Widget w, caddr_t client_data, caddr_t call_data)
688 wmGD.confirmDialogMapped = False;
690 } /* END OF FUNCTION CancelCB */
694 /*************************************<->*************************************
697 * ConfirmAction (pSD,nbr)
702 * Post a QuestionBox and ask for confirmation. If so, executes the
703 * appropriate action.
708 * nbr = action number
710 * pSD->screenTopLevel
715 * actionNbr = current QuestionBox widget index.
716 * confirmW[actionNbr] = QuestionBox widget.
722 *************************************<->***********************************/
724 void ConfirmAction (WmScreenData *pSD, int nbr)
729 Dimension width, height;
730 Widget dialogShellW = NULL;
731 XmString messageString;
732 static XmString defaultMessageString = NULL;
736 * If there is a system modal window, don't post another
737 * one. We need to think about a way to let a new system
738 * modal window be posted, and when unposted, restore the
739 * modal state of the current system modal window.
742 if(wmGD.systemModalActive)
747 if (pSD->confirmboxW[nbr] == NULL)
748 /* First time for this one */
750 #ifndef NO_MESSAGE_CATALOG
752 * Initialize messages
758 * Create a dialog popup shell with explicit keyboard policy.
762 XtSetArg(args[n], XmNx, (XtArgVal)
763 (DisplayWidth (DISPLAY, pSD->screen)/2)); n++;
764 XtSetArg(args[n], XmNy, (XtArgVal)
765 (DisplayHeight (DISPLAY, pSD->screen)/2)); n++;
766 XtSetArg(args[n], XtNallowShellResize, (XtArgVal) TRUE); n++;
767 XtSetArg(args[n], XtNkeyboardFocusPolicy, (XtArgVal) XmEXPLICIT); n++;
768 XtSetArg(args[n], XtNdepth,
769 (XtArgVal) DefaultDepth(DISPLAY, pSD->screen)); n++;
770 XtSetArg(args[n], XtNscreen,
771 (XtArgVal) ScreenOfDisplay(DISPLAY, pSD->screen)); n++;
774 XtCreatePopupShell ((String) WmNfeedback,
775 transientShellWidgetClass,
776 pSD->screenTopLevelW, args, n);
779 * Create a QuestionBox as a child of the popup shell.
780 * Set traversalOn and add callbacks for the OK and CANCEL buttons.
781 * Unmanage the HELP button.
785 XtSetArg(args[n], XmNdialogType, (XtArgVal) XmDIALOG_QUESTION); n++;
786 XtSetArg(args[n], XmNmessageAlignment, (XtArgVal) XmALIGNMENT_CENTER);
788 XtSetArg(args[n], XmNtraversalOn, (XtArgVal) TRUE); n++;
791 * In 1.2 confirmbox's widget name changed from the generic
792 * WmNconfirmbox (ie. 'confirmbox') to a more descriptive name
793 * so that each confirm dialog can be customized separately (e.g.
794 * "Mwm*confirmRestart*messageString: restart it?").
797 pSD->confirmboxW[nbr] =
798 XtCreateManagedWidget (confirm_widget[nbr], xmMessageBoxWidgetClass,
799 dialogShellW, args, n);
802 XtSetArg(args[n], XmNmessageString, &messageString); n++;
803 XtGetValues(pSD->confirmboxW[nbr], (ArgList) args, n);
805 if (defaultMessageString == NULL)
807 defaultMessageString = XmStringCreateLocalized ("");
813 * If the message string is the default, then put something
814 * 'reasonable' in instead.
817 if (XmStringCompare( messageString, defaultMessageString ))
819 messageString = XmStringCreateLocalized(confirm_mesg[nbr]);
820 XtSetArg(args[n], XmNmessageString, (XtArgVal) messageString); n++;
821 XtSetValues(pSD->confirmboxW[nbr], (ArgList) args, n);
822 XmStringFree(messageString);
826 XtSetArg (args[n], XmNtraversalOn, (XtArgVal) TRUE); n++;
827 XtSetArg (args[n], XmNhighlightThickness,
828 (XtArgVal) CB_HIGHLIGHT_THICKNESS); n++;
829 #ifndef NO_MESSAGE_CATALOG
830 XtSetArg(args[n], XmNlabelString, wmGD.okLabel); n++;
832 XtSetValues ( XmMessageBoxGetChild (pSD->confirmboxW[nbr],
833 XmDIALOG_OK_BUTTON), args, n);
834 #ifndef NO_MESSAGE_CATALOG
836 XtSetArg(args[n], XmNlabelString, wmGD.cancelLabel); n++;
838 XtSetValues ( XmMessageBoxGetChild (pSD->confirmboxW[nbr],
839 XmDIALOG_CANCEL_BUTTON), args, n);
840 XtAddCallback (pSD->confirmboxW[nbr], XmNokCallback,
841 (XtCallbackProc)OkCB, (XtPointer)pSD);
842 XtAddCallback (pSD->confirmboxW[nbr], XmNcancelCallback,
843 (XtCallbackProc)CancelCB, (XtPointer)NULL);
846 (XmMessageBoxGetChild (pSD->confirmboxW[nbr],
847 XmDIALOG_HELP_BUTTON));
849 XtRealizeWidget (dialogShellW);
852 * Center the DialogShell in the display.
856 XtSetArg(args[n], XmNheight, &height); n++;
857 XtSetArg(args[n], XmNwidth, &width); n++;
858 XtGetValues (dialogShellW, (ArgList) args, n);
860 x = (DisplayWidth (DISPLAY, pSD->screen) - ((int) width))/2;
861 y = (DisplayHeight (DISPLAY, pSD->screen) - ((int) height))/2;
863 XtSetArg(args[n], XmNx, (XtArgVal) x); n++;
864 XtSetArg(args[n], XmNy, (XtArgVal) y); n++;
865 XtSetValues (dialogShellW, (ArgList) args, n);
867 ManageWindow (pSD, XtWindow(dialogShellW), MANAGEW_CONFIRM_BOX);
871 ReManageDialog (pSD, pSD->confirmboxW[nbr]);
874 pSD->actionNbr = nbr;
878 wmGD.confirmDialogMapped = True;
880 } /* END OF FUNCTION ConfirmAction */
884 /*************************************<->*************************************
886 * ShowWaitState (flag)
891 * Enter/Leave the wait state.
896 * flag = TRUE for Enter, FALSE for Leave.
908 *************************************<->***********************************/
910 void ShowWaitState (Boolean flag)
916 unsigned int xHotspot;
917 unsigned int yHotspot;
925 if (wmGD.useLargeCursors)
927 width = time32_width;
928 height = time32_height;
929 bits = (char *)time32_bits;
930 maskBits = (char *)time32m_bits;
931 xHotspot = time32_x_hot;
932 yHotspot = time32_y_hot;
935 #endif /* LARGECURSORS */
938 width = time16_width;
939 height = time16_height;
940 bits = (char *)time16_bits;
941 maskBits = (char *)time16m_bits;
942 xHotspot = time16_x_hot;
943 yHotspot = time16_y_hot;
946 pixmap = XCreateBitmapFromData (DISPLAY,
947 DefaultRootWindow(DISPLAY), bits,
950 maskPixmap = XCreateBitmapFromData (DISPLAY,
951 DefaultRootWindow(DISPLAY), maskBits,
953 #ifdef INTEGRATION_TESTING_
954 xcolors[1].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
955 xcolors[0].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
956 #else /* INTEGRATION_TESTING */
958 xcolors[0].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
959 xcolors[1].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
961 #endif /* INTEGRATION_TESTING */
962 XQueryColors (DISPLAY,
963 DefaultColormapOfScreen(DefaultScreenOfDisplay
966 waitCursor = XCreatePixmapCursor (DISPLAY, pixmap, maskPixmap,
967 &(xcolors[0]), &(xcolors[1]),
969 XFreePixmap (DISPLAY, pixmap);
970 XFreePixmap (DISPLAY, maskPixmap);
975 XGrabPointer (DISPLAY, DefaultRootWindow(DISPLAY), FALSE,
976 0, GrabModeAsync, GrabModeAsync, None,
977 waitCursor, CurrentTime);
978 XGrabKeyboard (DISPLAY, DefaultRootWindow(DISPLAY), FALSE,
979 GrabModeAsync, GrabModeAsync, CurrentTime);
983 XUngrabPointer (DISPLAY, CurrentTime);
984 XUngrabKeyboard (DISPLAY, CurrentTime);
987 } /* END OF FUNCTION ShowWaitState */
991 /*************************************<->*************************************
998 * This function determines whether a server supports large cursors. It it
999 * does large feedback cursors are used in some cases (wait state and
1000 * system modal state); otherwise smaller (16x16) standard cursors are used.
1004 * wmGD.useLargeCusors = set to True if larger cursors are supported.
1006 *************************************<->***********************************/
1008 void InitCursorInfo (void)
1010 unsigned int cWidth;
1011 unsigned int cHeight;
1013 wmGD.useLargeCursors = False;
1015 if (XQueryBestCursor (DISPLAY, DefaultRootWindow(DISPLAY),
1016 32, 32, &cWidth, &cHeight))
1018 if ((cWidth >= 32) && (cHeight >= 32))
1020 wmGD.useLargeCursors = True;
1024 } /* END OF FUNCTION InitCursorInfo */