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 librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: MainWindow.C /main/13 1998/04/06 13:22:40 mgreess $ */
27 * $TOG: MainWindow.C /main/13 1998/04/06 13:22:40 mgreess $
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special
32 * restrictions in a confidential disclosure agreement bertween
33 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35 * Sun's specific written approval. This documment and all copies
36 * and derivative works thereof must be returned or destroyed at
39 * Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
44 ///////////////////////////////////////////////////////////////////////////////
45 //////////////////////////////////////////////////////////////////////////////
46 // This example code is from the book:
48 // Object-Oriented Programming with C++ and OSF/Motif
51 // Prentice Hall, 1992
54 // Copyright 1991 by Prentice Hall
55 // All Rights Reserved
57 // Permission to use, copy, modify, and distribute this software for
58 // any purpose except publication and without fee is hereby granted, provided
59 // that the above copyright notice appear in all copies of the software.
60 ///////////////////////////////////////////////////////////////////////////////
61 //////////////////////////////////////////////////////////////////////////////
64 ////////////////////////////////////////////////////////////////////
65 // MainWindow.C: Support a toplevel window
66 ////////////////////////////////////////////////////////////////////
70 #include <Xm/Protocols.h>
71 #include <Xm/AtomMgr.h>
74 #include <Dt/Session.h>
75 #include <DtMail/IO.hh>
76 #include <X11/Shell.h>
77 #include <X11/Xmu/Editres.h>
78 #include "Application.h"
79 #include "MainWindow.h"
82 // The following headers are private to CDE and should NOT be required
83 // but unfortunately are.
86 #include <Dt/HourGlass.h>
90 #include <Dt/IconFile.h>
92 // This is a private CDE function that should be public, but is not,
93 // and does not even have a prototype in a header. Yes, it is required.
95 extern "C" Pixmap _DtGetMask(Screen * screen, char * image_name);
98 static const char * DefaultIcon = "Dtablnk";
100 static const unsigned long FLASH_INTERVAL = 250; // milliseconds
102 MainWindow::MainWindow( char *name, Boolean allowResize ) : UIComponent ( name )
107 _window_invert = NULL;
109 _allow_resize = allowResize;
111 assert ( theApplication != NULL ); // Application object must exist
112 // before any MainWindow object
113 theApplication->registerWindow ( this );
117 MainWindow::initialize( )
121 // All toplevel windows in the MotifApp framework are
122 // implemented as a popup shell off the Application's
125 // XmNdeleteResponse is being set to DO_NOTHING so
126 // that the user can Cancel their close request.
128 _w = XtVaCreatePopupShell ( _name,
129 topLevelShellWidgetClass,
130 theApplication->baseWidget(),
131 XmNdeleteResponse, XmDO_NOTHING,
132 XmNallowShellResize, _allow_resize,
137 _w, (EventMask) 0, True,
138 (XtEventHandler) _XEditResCheckMessages, NULL);
141 installDestroyHandler();
143 // Use a Motif XmMainWindow widget to handle window layout
145 _main = XtCreateManagedWidget ( "mainWindow",
146 xmMainWindowWidgetClass,
149 printHelpId("_main", _main);
150 /* install callback */
151 // XtAddCallback(_main, XmNhelpCallback, HelpCB, helpId);
152 XtAddCallback(_main, XmNhelpCallback,
153 HelpCB, (void *)"_HOMETOPIC");
155 // Called derived class to create the work area
157 _workArea = createWorkArea ( _main );
158 assert ( _workArea != NULL );
160 // Designate the _workArea widget as the XmMainWindow
161 // widget's XmNworkWindow widget
163 XtVaSetValues ( _main,
164 XmNworkWindow, _workArea,
167 Atom WM_DELETE_WINDOW=XmInternAtom( XtDisplay( _w ),
171 XmAddWMProtocolCallback( _w,
173 ( XtCallbackProc ) quitCallback,
177 // Why are we setting the icon to Dtablnk. This is simply going to
178 // be overriden by some other function setting it to the appropriate
180 setIconName(DefaultIcon);
183 _window_invert = NULL;
185 _flash_owin = (Window) NULL;
186 _flash_iwin = (Window) NULL;
187 memset((char*) &(this->_window_attributes), 0, sizeof(XWindowAttributes));
189 // Manage the work area if the derived class hasn't already.
191 if ( !XtIsManaged ( _workArea ) )
192 XtManageChild ( _workArea );
195 appWorkspaces = theApplication->getAppWorkspaceList();
196 setWorkspacesOccupied(appWorkspaces);
199 MainWindow::~MainWindow( )
201 // Unregister this window with the Application object
204 Atom WM_DELETE_WINDOW=XmInternAtom( XtDisplay( _w ),
207 XmRemoveWMProtocolCallback( _w,
209 ( XtCallbackProc ) quitCallback,
212 if (_icon_invert) XFreeGC(XtDisplay(_w), _icon_invert);
213 if (_window_invert) XFreeGC(XtDisplay(_w), _window_invert);
214 if (_flash_iwin != (Window) NULL)
215 XDestroyWindow( XtDisplay(_w), _flash_iwin );
216 if (_flash_owin != (Window) NULL)
217 XDestroyWindow( XtDisplay(_w), _flash_owin );
220 theApplication->unregisterWindow ( this );
224 MainWindow::enableWorkAreaResize()
226 XtVaSetValues(_workArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
230 MainWindow::disableWorkAreaResize()
232 XtVaSetValues(_workArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
238 assert ( _w != NULL );
239 XtPopup ( _w, XtGrabNone );
241 // Map the window, in case the window is iconified
243 if ( XtIsRealized ( _w ) )
244 XMapRaised ( XtDisplay ( _w ), XtWindow ( _w ) );
248 MainWindow::unmanage()
250 assert ( _w != NULL );
255 MainWindow::iconify()
257 assert ( _w != NULL );
259 // Set the widget to have an initial iconic state
260 // in case the base widget has not yet been realized
262 XtVaSetValues ( _w, XmNiconic, TRUE, NULL );
264 // If the widget has already been realized,
265 // iconify the window
267 if ( XtIsRealized ( _w ) )
268 XIconifyWindow ( XtDisplay ( _w ), XtWindow ( _w ), 0 );
272 MainWindow::setIconTitle(const char * title)
274 XtVaSetValues(_w, XmNiconName, title, NULL);
278 MainWindow::setIconName(const char * path)
280 char * icon_filename = XmGetIconFileName(XtScreen(_w),
282 (char *)path, // Bug!
286 if (icon_filename == NULL) {
290 Pixel fg = 0, bg = 0;
292 getIconColors(fg, bg);
294 _icon = XmGetPixmap(XtScreen(_w),
298 Pixmap icon_mask_map = _DtGetMask(XtScreen(_w), icon_filename);
300 if (!_icon || !icon_mask_map) {
305 XmNiconPixmap, _icon,
306 XmNiconMask, icon_mask_map,
309 // Build the inverted icon mask for flashing.
312 XFreeGC(XtDisplay(_w), _icon_invert);
317 gc_vals.foreground = bg;
318 gc_vals.function = GXxor;
319 _icon_invert = XCreateGC(XtDisplay(_w), _icon, GCForeground | GCFunction,
322 XtFree(icon_filename);
326 MainWindow::busyCursor()
328 // Do nothing if the widget has not been realized
330 if (XtIsRealized(_w)) {
331 _DtTurnOnHourGlass(_w);
336 MainWindow::normalCursor()
338 // Do nothing if the widget has not been realized
340 if (XtIsRealized ( _w ))
342 _DtTurnOffHourGlass(_w);
347 MainWindow::setStatus(const char *)
353 MainWindow::clearStatus(void)
359 MainWindow::title(const char *text )
361 XtVaSetValues ( _w, XmNtitle, (char *)text, NULL );
365 MainWindow::quitCallback( Widget,
366 XtPointer clientData,
367 XmAnyCallbackStruct *)
369 MainWindow *window=( MainWindow *) clientData;
374 MainWindow::getIconColors(Pixel & fore, Pixel & back)
377 XmNforeground, &fore,
378 XmNbackground, &back,
388 getWindowState(Widget w)
390 Atom wmStateAtom, actualType;
393 unsigned long nitems, leftover;
396 /* Getting the WM_STATE property to see if iconified or not */
397 wmStateAtom = XInternAtom(XtDisplay(w), "WM_STATE", False);
399 XGetWindowProperty (XtDisplay(w), XtWindow(w),
401 (long)BUFSIZ, False, wmStateAtom, &actualType,
402 &actualFormat, &nitems, &leftover,
403 (unsigned char **) &wmState);
406 retval = wmState->state;
410 free((void*) wmState);
415 MainWindow::flash(const int count)
417 XWindowAttributes window_attributes;
419 if (count == 0) return;
420 if (_flashing > 0) return;
422 if (_window_invert == NULL) {
423 // Create a GC to flash the window.
427 getIconColors(fg, bg);
429 gc_vals.foreground = bg;
430 gc_vals.function = GXxor;
431 _window_invert = XCreateGC(XtDisplay(_w), XtWindow(_w),
432 GCForeground | GCFunction, &gc_vals);
433 XSetSubwindowMode(XtDisplay(_w), _window_invert, IncludeInferiors);
436 _last_state = getWindowState(_w);
439 // The original method here, to invert the window and timeout
440 // before inverting back to the original (pixels), breaks when
441 // the window is left with pixels XOR'd in the flash ON state.
443 // One quick fix, uses a transparent window (or windows) on top
444 // of the window to be flashed. The temp window(s) are used to
445 // prevent updates while flash is ON and/or cause a full update
446 // (expose) after each flash.
448 // First, (this part optional) put an "InputOnly" window on top of
449 // the window to be flashed and ignore all events to this window.
450 // This has the effect of preventing user input (events) from
451 // causing application updates to the window. This temp window
452 // can be left up (with the wait cursor) until flashing is done.
454 // Next, handle expose events by using a transparent "InputOutput"
455 // window on top of everything only when flash is ON. This has
456 // the effect of preventing expose events from causing application
457 // updates to the real window when flash is ON. It especially,
458 // ensures other problems (e.g. updates to the window caused by
459 // other application timeout events and overlapping window pixels
460 // from an expose event) are cleaned up by an expose event when
461 // this temp window is unmapped or destroyed (between each flash).
464 XGetWindowAttributes(XtDisplay(_w), XtWindow(_w), &window_attributes);
466 if ((Window) NULL != _flash_owin &&
467 (window_attributes.width != _window_attributes.width ||
468 window_attributes.height != _window_attributes.height ||
469 window_attributes.border_width != _window_attributes.border_width))
471 XDestroyWindow( XtDisplay(_w), _flash_iwin );
472 XDestroyWindow( XtDisplay(_w), _flash_owin );
473 _flash_iwin = (Window) NULL;
474 _flash_owin = (Window) NULL;
477 if ((Window) NULL == _flash_owin)
479 XSetWindowAttributes sw_attr;
481 memcpy((char*) &(this->_window_attributes),
482 (char*) &window_attributes,
483 sizeof(window_attributes));
485 sw_attr.event_mask = 0;
486 _flash_iwin = XCreateWindow(
487 XtDisplay(_w), XtWindow(_w), 0, 0,
488 _window_attributes.width, _window_attributes.height,
489 _window_attributes.border_width, (int) CopyFromParent,
490 InputOnly, CopyFromParent,
491 CWEventMask, &sw_attr );
492 XMapWindow( XtDisplay(_w), _flash_iwin );
493 _flash_owin = XCreateWindow(
494 XtDisplay(_w), XtWindow(_w), 0, 0,
495 _window_attributes.width, _window_attributes.height,
496 _window_attributes.border_width, (int) CopyFromParent,
497 InputOutput, CopyFromParent,
498 CWEventMask, &sw_attr );
501 _flashing = count * 2;
503 XtWidgetToApplicationContext(_w),
504 FLASH_INTERVAL, flashCallback, this);
508 MainWindow::flashCallback(XtPointer client_data, XtIntervalId * interval_id)
510 MainWindow * mw = (MainWindow *)client_data;
512 mw->doFlash(interval_id);
516 MainWindow::doFlash(XtIntervalId *)
518 static int busy_cursor = 0;
519 int state = getWindowState(_w);
521 // We are going to make things flash an even number of times.
522 // to do this, we will lie about the state, and leave it at the
523 // old state for one iteration.
524 if (state != _last_state && (_flashing % 2) != 0)
532 if (state == IconicState) {
533 Pixmap image = _icon;
535 XFillRectangle(XtDisplay(_w), image, _icon_invert, 0, 0, 48, 48);
536 XtVaSetValues(_w, XmNiconPixmap, NULL, NULL);
537 XtVaSetValues(_w, XmNiconPixmap, image, NULL);
539 else if (state != 0) {
541 // Map temp window to prevent expose updates and other
542 // application event updates ... when flash is on.
543 if ( (_flashing % 2) == 0 )
544 XMapWindow( XtDisplay(_w), _flash_owin );
547 XtDisplay(_w), XtWindow(_w),
548 _window_invert, 0, 0,
549 _window_attributes.width, _window_attributes.height);
551 // Remove temp window to update display when flash is off.
552 if ( (_flashing % 2) != 0 )
553 XUnmapWindow( XtDisplay(_w), _flash_owin );
560 XtWidgetToApplicationContext(_w),
561 FLASH_INTERVAL, flashCallback, this);
565 XUnmapWindow( XtDisplay(_w), _flash_iwin );
566 XUnmapWindow( XtDisplay(_w), _flash_owin );
573 MainWindow::isIconified()
576 Atom wmStateAtom, actualType;
578 unsigned long nitems, leftover;
580 Boolean retval = FALSE;
582 assert ( _w != NULL );
584 /* Getting the WM_STATE property to see if iconified or not */
585 wmStateAtom = XInternAtom(XtDisplay(_w), "WM_STATE", False);
587 XGetWindowProperty (XtDisplay(_w), XtWindow(_w),
589 (long)BUFSIZ, False, wmStateAtom, &actualType,
590 &actualFormat, &nitems, &leftover,
591 (unsigned char **) &wmState);
594 if (wmState && wmState->state == IconicState)
597 free((void*) wmState);
601 /************************************************************************
603 ************************************************************************/
605 MainWindow::MbStrchr(char *str, int ch)
607 size_t mbCurMax = MB_CUR_MAX;
608 wchar_t targetChar, curChar;
610 int i, numBytes, byteLen;
612 if(mbCurMax <= 1) return strchr(str, ch);
615 mbtowc(&targetChar, &tmpChar, mbCurMax);
616 for(i = 0, numBytes = 0, byteLen = strlen(str); i < byteLen; i += numBytes)
618 numBytes = mbtowc(&curChar, &str[i], mbCurMax);
619 if(curChar == targetChar) return &str[i];
625 MainWindow::setWorkspacesOccupied(char *workspaces)
628 Atom *workspace_atoms = NULL;
635 ptr = MbStrchr (workspaces, ' ');
637 if (ptr != NULL) *ptr = '\0';
639 workspace_atoms = (Atom*) XtRealloc(
640 (char *) workspace_atoms,
641 sizeof(Atom)*(nworkspaces+1));
642 workspace_atoms[nworkspaces] = XmInternAtom(
650 workspaces = ptr + 1;
652 } while (ptr != NULL);
654 DtWsmSetWorkspacesOccupied(
655 XtDisplay(_w), XtWindow (_w),
656 workspace_atoms, nworkspaces);
658 XtFree ((char *) workspace_atoms);
659 workspace_atoms = NULL;
665 Screen *currentScreen;
668 screen = XDefaultScreen(XtDisplay(_w));
669 currentScreen = XScreenOfDisplay(XtDisplay(_w), screen);
670 rootWindow = RootWindowOfScreen(currentScreen);
672 if (DtWsmGetCurrentWorkspace(
675 &pCurrent) == Success)
676 DtWsmSetWorkspacesOccupied(