1 /* $TOG: MainWindow.C /main/13 1998/04/06 13:22:40 mgreess $ */
5 * $TOG: MainWindow.C /main/13 1998/04/06 13:22:40 mgreess $
7 * RESTRICTED CONFIDENTIAL INFORMATION:
9 * The information in this document is subject to special
10 * restrictions in a confidential disclosure agreement bertween
11 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
12 * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
13 * Sun's specific written approval. This documment and all copies
14 * and derivative works thereof must be returned or destroyed at
17 * Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
22 ///////////////////////////////////////////////////////////////////////////////
23 //////////////////////////////////////////////////////////////////////////////
24 // This example code is from the book:
26 // Object-Oriented Programming with C++ and OSF/Motif
29 // Prentice Hall, 1992
32 // Copyright 1991 by Prentice Hall
33 // All Rights Reserved
35 // Permission to use, copy, modify, and distribute this software for
36 // any purpose except publication and without fee is hereby granted, provided
37 // that the above copyright notice appear in all copies of the software.
38 ///////////////////////////////////////////////////////////////////////////////
39 //////////////////////////////////////////////////////////////////////////////
42 ////////////////////////////////////////////////////////////////////
43 // MainWindow.C: Support a toplevel window
44 ////////////////////////////////////////////////////////////////////
48 #include <Xm/Protocols.h>
49 #include <Xm/AtomMgr.h>
52 #include <Dt/Session.h>
53 #include <DtMail/IO.hh>
54 #include <X11/Shell.h>
55 #include <X11/Xmu/Editres.h>
56 #include "Application.h"
57 #include "MainWindow.h"
60 // The following headers are private to CDE and should NOT be required
61 // but unfortunately are.
64 #include <Dt/HourGlass.h>
68 #include <Dt/IconFile.h>
70 // This is a private CDE function that should be public, but is not,
71 // and does not even have a prototype in a header. Yes, it is required.
73 extern "C" Pixmap _DtGetMask(Screen * screen, char * image_name);
76 static const char * DefaultIcon = "Dtablnk";
78 static const unsigned long FLASH_INTERVAL = 250; // milliseconds
80 MainWindow::MainWindow( char *name, Boolean allowResize ) : UIComponent ( name )
85 _window_invert = NULL;
87 _allow_resize = allowResize;
89 assert ( theApplication != NULL ); // Application object must exist
90 // before any MainWindow object
91 theApplication->registerWindow ( this );
95 MainWindow::initialize( )
99 // All toplevel windows in the MotifApp framework are
100 // implemented as a popup shell off the Application's
103 // XmNdeleteResponse is being set to DO_NOTHING so
104 // that the user can Cancel their close request.
106 _w = XtVaCreatePopupShell ( _name,
107 topLevelShellWidgetClass,
108 theApplication->baseWidget(),
109 XmNdeleteResponse, XmDO_NOTHING,
110 XmNallowShellResize, _allow_resize,
115 _w, (EventMask) 0, True,
116 (XtEventHandler) _XEditResCheckMessages, NULL);
119 installDestroyHandler();
121 // Use a Motif XmMainWindow widget to handle window layout
123 _main = XtCreateManagedWidget ( "mainWindow",
124 xmMainWindowWidgetClass,
127 printHelpId("_main", _main);
128 /* install callback */
129 // XtAddCallback(_main, XmNhelpCallback, HelpCB, helpId);
130 XtAddCallback(_main, XmNhelpCallback,
131 HelpCB, "_HOMETOPIC");
133 // Called derived class to create the work area
135 _workArea = createWorkArea ( _main );
136 assert ( _workArea != NULL );
138 // Designate the _workArea widget as the XmMainWindow
139 // widget's XmNworkWindow widget
141 XtVaSetValues ( _main,
142 XmNworkWindow, _workArea,
145 Atom WM_DELETE_WINDOW=XmInternAtom( XtDisplay( _w ),
149 XmAddWMProtocolCallback( _w,
151 ( XtCallbackProc ) quitCallback,
155 // Why are we setting the icon to Dtablnk. This is simply going to
156 // be overriden by some other function setting it to the appropriate
158 setIconName(DefaultIcon);
161 _window_invert = NULL;
163 _flash_owin = (Window) NULL;
164 _flash_iwin = (Window) NULL;
165 memset((char*) &(this->_window_attributes), 0, sizeof(XWindowAttributes));
167 // Manage the work area if the derived class hasn't already.
169 if ( !XtIsManaged ( _workArea ) )
170 XtManageChild ( _workArea );
173 appWorkspaces = theApplication->getAppWorkspaceList();
174 setWorkspacesOccupied(appWorkspaces);
177 MainWindow::~MainWindow( )
179 // Unregister this window with the Application object
182 Atom WM_DELETE_WINDOW=XmInternAtom( XtDisplay( _w ),
185 XmRemoveWMProtocolCallback( _w,
187 ( XtCallbackProc ) quitCallback,
190 if (_icon_invert) XFreeGC(XtDisplay(_w), _icon_invert);
191 if (_window_invert) XFreeGC(XtDisplay(_w), _window_invert);
192 if (_flash_iwin != (Window) NULL)
193 XDestroyWindow( XtDisplay(_w), _flash_iwin );
194 if (_flash_owin != (Window) NULL)
195 XDestroyWindow( XtDisplay(_w), _flash_owin );
198 theApplication->unregisterWindow ( this );
202 MainWindow::enableWorkAreaResize()
204 XtVaSetValues(_workArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
208 MainWindow::disableWorkAreaResize()
210 XtVaSetValues(_workArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
216 assert ( _w != NULL );
217 XtPopup ( _w, XtGrabNone );
219 // Map the window, in case the window is iconified
221 if ( XtIsRealized ( _w ) )
222 XMapRaised ( XtDisplay ( _w ), XtWindow ( _w ) );
226 MainWindow::unmanage()
228 assert ( _w != NULL );
233 MainWindow::iconify()
235 assert ( _w != NULL );
237 // Set the widget to have an initial iconic state
238 // in case the base widget has not yet been realized
240 XtVaSetValues ( _w, XmNiconic, TRUE, NULL );
242 // If the widget has already been realized,
243 // iconify the window
245 if ( XtIsRealized ( _w ) )
246 XIconifyWindow ( XtDisplay ( _w ), XtWindow ( _w ), 0 );
250 MainWindow::setIconTitle(const char * title)
252 XtVaSetValues(_w, XmNiconName, title, NULL);
256 MainWindow::setIconName(const char * path)
258 char * icon_filename = XmGetIconFileName(XtScreen(_w),
260 (char *)path, // Bug!
264 if (icon_filename == NULL) {
268 Pixel fg = 0, bg = 0;
270 getIconColors(fg, bg);
272 _icon = XmGetPixmap(XtScreen(_w),
276 Pixmap icon_mask_map = _DtGetMask(XtScreen(_w), icon_filename);
278 if (!_icon || !icon_mask_map) {
283 XmNiconPixmap, _icon,
284 XmNiconMask, icon_mask_map,
287 // Build the inverted icon mask for flashing.
290 XFreeGC(XtDisplay(_w), _icon_invert);
295 gc_vals.foreground = bg;
296 gc_vals.function = GXxor;
297 _icon_invert = XCreateGC(XtDisplay(_w), _icon, GCForeground | GCFunction,
300 XtFree(icon_filename);
304 MainWindow::busyCursor()
306 // Do nothing if the widget has not been realized
308 if (XtIsRealized(_w)) {
309 _DtTurnOnHourGlass(_w);
314 MainWindow::normalCursor()
316 // Do nothing if the widget has not been realized
318 if (XtIsRealized ( _w ))
320 _DtTurnOffHourGlass(_w);
325 MainWindow::setStatus(const char *)
331 MainWindow::clearStatus(void)
337 MainWindow::title(const char *text )
339 XtVaSetValues ( _w, XmNtitle, (char *)text, NULL );
343 MainWindow::quitCallback( Widget,
344 XtPointer clientData,
345 XmAnyCallbackStruct *)
347 MainWindow *window=( MainWindow *) clientData;
352 MainWindow::getIconColors(Pixel & fore, Pixel & back)
355 XmNforeground, &fore,
356 XmNbackground, &back,
366 getWindowState(Widget w)
368 Atom wmStateAtom, actualType;
371 unsigned long nitems, leftover;
374 /* Getting the WM_STATE property to see if iconified or not */
375 wmStateAtom = XInternAtom(XtDisplay(w), "WM_STATE", False);
377 XGetWindowProperty (XtDisplay(w), XtWindow(w),
379 (long)BUFSIZ, False, wmStateAtom, &actualType,
380 &actualFormat, &nitems, &leftover,
381 (unsigned char **) &wmState);
384 retval = wmState->state;
388 free((void*) wmState);
393 MainWindow::flash(const int count)
395 XWindowAttributes window_attributes;
397 if (count == 0) return;
398 if (_flashing > 0) return;
400 if (_window_invert == NULL) {
401 // Create a GC to flash the window.
405 getIconColors(fg, bg);
407 gc_vals.foreground = bg;
408 gc_vals.function = GXxor;
409 _window_invert = XCreateGC(XtDisplay(_w), XtWindow(_w),
410 GCForeground | GCFunction, &gc_vals);
411 XSetSubwindowMode(XtDisplay(_w), _window_invert, IncludeInferiors);
414 _last_state = getWindowState(_w);
417 // The original method here, to invert the window and timeout
418 // before inverting back to the original (pixels), breaks when
419 // the window is left with pixels XOR'd in the flash ON state.
421 // One quick fix, uses a transparent window (or windows) on top
422 // of the window to be flashed. The temp window(s) are used to
423 // prevent updates while flash is ON and/or cause a full update
424 // (expose) after each flash.
426 // First, (this part optional) put an "InputOnly" window on top of
427 // the window to be flashed and ignore all events to this window.
428 // This has the effect of preventing user input (events) from
429 // causing application updates to the window. This temp window
430 // can be left up (with the wait cursor) until flashing is done.
432 // Next, handle expose events by using a transparent "InputOutput"
433 // window on top of everything only when flash is ON. This has
434 // the effect of preventing expose events from causing application
435 // updates to the real window when flash is ON. It especially,
436 // ensures other problems (e.g. updates to the window caused by
437 // other application timeout events and overlapping window pixels
438 // from an expose event) are cleaned up by an expose event when
439 // this temp window is unmapped or destroyed (between each flash).
442 XGetWindowAttributes(XtDisplay(_w), XtWindow(_w), &window_attributes);
444 if ((Window) NULL != _flash_owin &&
445 (window_attributes.width != _window_attributes.width ||
446 window_attributes.height != _window_attributes.height ||
447 window_attributes.border_width != _window_attributes.border_width))
449 XDestroyWindow( XtDisplay(_w), _flash_iwin );
450 XDestroyWindow( XtDisplay(_w), _flash_owin );
451 _flash_iwin = (Window) NULL;
452 _flash_owin = (Window) NULL;
455 if ((Window) NULL == _flash_owin)
457 XSetWindowAttributes sw_attr;
459 memcpy((char*) &(this->_window_attributes),
460 (char*) &window_attributes,
461 sizeof(window_attributes));
463 sw_attr.event_mask = 0;
464 _flash_iwin = XCreateWindow(
465 XtDisplay(_w), XtWindow(_w), 0, 0,
466 _window_attributes.width, _window_attributes.height,
467 _window_attributes.border_width, (int) CopyFromParent,
468 InputOnly, CopyFromParent,
469 CWEventMask, &sw_attr );
470 XMapWindow( XtDisplay(_w), _flash_iwin );
471 _flash_owin = XCreateWindow(
472 XtDisplay(_w), XtWindow(_w), 0, 0,
473 _window_attributes.width, _window_attributes.height,
474 _window_attributes.border_width, (int) CopyFromParent,
475 InputOutput, CopyFromParent,
476 CWEventMask, &sw_attr );
479 _flashing = count * 2;
481 XtWidgetToApplicationContext(_w),
482 FLASH_INTERVAL, flashCallback, this);
486 MainWindow::flashCallback(XtPointer client_data, XtIntervalId * interval_id)
488 MainWindow * mw = (MainWindow *)client_data;
490 mw->doFlash(interval_id);
494 MainWindow::doFlash(XtIntervalId *)
496 static int busy_cursor = 0;
497 int state = getWindowState(_w);
499 // We are going to make things flash an even number of times.
500 // to do this, we will lie about the state, and leave it at the
501 // old state for one iteration.
502 if (state != _last_state && (_flashing % 2) != 0)
510 if (state == IconicState) {
511 Pixmap image = _icon;
513 XFillRectangle(XtDisplay(_w), image, _icon_invert, 0, 0, 48, 48);
514 XtVaSetValues(_w, XmNiconPixmap, NULL, NULL);
515 XtVaSetValues(_w, XmNiconPixmap, image, NULL);
517 else if (state != 0) {
519 // Map temp window to prevent expose updates and other
520 // application event updates ... when flash is on.
521 if ( (_flashing % 2) == 0 )
522 XMapWindow( XtDisplay(_w), _flash_owin );
525 XtDisplay(_w), XtWindow(_w),
526 _window_invert, 0, 0,
527 _window_attributes.width, _window_attributes.height);
529 // Remove temp window to update display when flash is off.
530 if ( (_flashing % 2) != 0 )
531 XUnmapWindow( XtDisplay(_w), _flash_owin );
538 XtWidgetToApplicationContext(_w),
539 FLASH_INTERVAL, flashCallback, this);
543 XUnmapWindow( XtDisplay(_w), _flash_iwin );
544 XUnmapWindow( XtDisplay(_w), _flash_owin );
551 MainWindow::isIconified()
554 Atom wmStateAtom, actualType;
556 unsigned long nitems, leftover;
558 Boolean retval = FALSE;
560 assert ( _w != NULL );
562 /* Getting the WM_STATE property to see if iconified or not */
563 wmStateAtom = XInternAtom(XtDisplay(_w), "WM_STATE", False);
565 XGetWindowProperty (XtDisplay(_w), XtWindow(_w),
567 (long)BUFSIZ, False, wmStateAtom, &actualType,
568 &actualFormat, &nitems, &leftover,
569 (unsigned char **) &wmState);
572 if (wmState && wmState->state == IconicState)
575 free((void*) wmState);
579 /************************************************************************
581 ************************************************************************/
583 MainWindow::MbStrchr(char *str, int ch)
585 size_t mbCurMax = MB_CUR_MAX;
586 wchar_t targetChar, curChar;
588 int i, numBytes, byteLen;
590 if(mbCurMax <= 1) return strchr(str, ch);
593 mbtowc(&targetChar, &tmpChar, mbCurMax);
594 for(i = 0, numBytes = 0, byteLen = strlen(str); i < byteLen; i += numBytes)
596 numBytes = mbtowc(&curChar, &str[i], mbCurMax);
597 if(curChar == targetChar) return &str[i];
603 MainWindow::setWorkspacesOccupied(char *workspaces)
606 Atom *workspace_atoms = NULL;
613 ptr = MbStrchr (workspaces, ' ');
615 if (ptr != NULL) *ptr = '\0';
617 workspace_atoms = (Atom*) XtRealloc(
618 (char *) workspace_atoms,
619 sizeof(Atom)*(nworkspaces+1));
620 workspace_atoms[nworkspaces] = XmInternAtom(
628 workspaces = ptr + 1;
630 } while (ptr != NULL);
632 DtWsmSetWorkspacesOccupied(
633 XtDisplay(_w), XtWindow (_w),
634 workspace_atoms, nworkspaces);
636 XtFree ((char *) workspace_atoms);
637 workspace_atoms = NULL;
643 Screen *currentScreen;
646 screen = XDefaultScreen(XtDisplay(_w));
647 currentScreen = XScreenOfDisplay(XtDisplay(_w), screen);
648 rootWindow = RootWindowOfScreen(currentScreen);
650 if (DtWsmGetCurrentWorkspace(
653 &pCurrent) == Success)
654 DtWsmSetWorkspacesOccupied(