Back to index

plt-scheme  4.2.1
Frame.cc
Go to the documentation of this file.
00001 /*                                                      -*- C++ -*-
00002  *
00003  * Purpose: base class for all frames
00004  *
00005  * Authors: Markus Holzem and Julian Smart
00006  *
00007  * Copyright: (C) 2004-2009 PLT Scheme Inc.
00008  * Copyright: (C) 1995, AIAI, University of Edinburgh (Julian)
00009  * Copyright: (C) 1995, GNU (Markus)
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00027 #ifdef __GNUG__
00028 #pragma implementation "Frame.h"
00029 #endif
00030 
00031 #define  Uses_XtIntrinsic
00032 #define  Uses_wxApp
00033 #define  Uses_wxFrame
00034 #define  Uses_wxGDI
00035 #define  Uses_wxLayout
00036 #define  Uses_wxList
00037 #define  Uses_wxMenuBar
00038 #define  Uses_wxMessage
00039 #define  Uses_wxTypeTree
00040 #define  Uses_wxMemoryDC
00041 #include "wx.h"
00042 #define  Uses_ShellWidget
00043 #define  Uses_BoardWidget
00044 #include "widgets.h"
00045 #include "../../contrib/xpm/lib/xpm.h"
00046 #include <X11/Xatom.h>
00047 #include "wx_visual.h"
00048 
00049 #include <sys/time.h>
00050 #include <sys/types.h>
00051 #include <unistd.h>
00052 
00053 /* XPM */
00054 static char * plt_xpm[] = {
00055 "16 16 5 1",
00056 "      c None",
00057 ".     c #000000",
00058 "-     c #FF0000",
00059 ",     c #0000FF",
00060 "!     c #FFFFFF",
00061 "................",
00062 ".....,,,,,,.....",
00063 "...--!!,,,,,,...",
00064 "..-----!,,,,,,..",
00065 "..-----!!,,,,,..",
00066 ".-------!,,,,,,.",
00067 ".-------!!,,,,,.",
00068 ".------!!!,,,,,.",
00069 ".-----!!-!!,,,,.",
00070 ".-----!---!,,,,.",
00071 ".----!!---!!,,,.",
00072 "..---!-----!,,..",
00073 "..--!!-----!!,..",
00074 "...-!-------!...",
00075 ".....------.....",
00076 "................"};
00077 
00078 #define plt_width 16
00079 #define plt_height 16
00080 static char plt_xbm[] = {
00081  0xe0,0x07,0xf8,0x1f,0xfc,0x3f,0xfe,0x7f,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,
00082  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x7f,0xfe,0x7f,0xfc,0x3f,0xf8,0x1f,
00083  0xe0,0x07};
00084 
00085 Pixmap plt_icon, plt_mask;
00086 
00087 //-----------------------------------------------------------------------------
00088 // create and destroy frame
00089 //-----------------------------------------------------------------------------
00090 
00091 wxFrame::wxFrame(void) : wxPanel()
00092 {
00093     __type = wxTYPE_FRAME;
00094 
00095     menubar         = NULL;
00096     status          = NULL;
00097     num_status      = 0;
00098 
00099     SetShown(FALSE);
00100 }
00101 
00102 wxFrame::wxFrame(wxFrame *parent, char *title,
00103                int x, int y, int width, int height, int style, char *name)
00104     : wxPanel()
00105 {
00106     __type = wxTYPE_FRAME;
00107 
00108     menubar         = NULL;
00109     status          = NULL;
00110     num_status      = 0;
00111 
00112     Create(parent, title, x, y, width, height, style, name);
00113 
00114     SetShown(FALSE);
00115 }
00116 
00117 wxFrame::~wxFrame(void)
00118 {
00119     wxChildList *tlf;
00120 
00121     // hide frame
00122     Show(FALSE);
00123     // destroy children first to popdown child frames
00124     DestroyChildren();
00125     // adjust list of top level frames
00126     tlf = wxTopLevelFrames(this);
00127     tlf->DeleteObject(this);
00128 }
00129 
00130 /* Used to ensure that hide-&-show within an event cycle works */
00131 static void wxFrameMapProc(Widget w, XtPointer clientData, 
00132                         XCrossingEvent * event)
00133 {
00134   wxFrame *frame = (wxFrame *)GET_SAFEREF(clientData);
00135 
00136   if (frame) {
00137     XEvent *e = (XEvent *)event;
00138 
00139     if (e->xany.type == MapNotify && e->xmap.window == XtWindow(w)) {
00140       if (!frame->IsShown()) {
00141        /* We really wanted this to be hidden! */
00142        XtUnmapWidget(w);
00143       }
00144     }
00145   }
00146 }
00147 
00148 extern "C" void *scheme_current_process;
00149 
00150 /* Copied off a newsgroup somewhere: */
00151 typedef struct {
00152   long flags;
00153   long functions;
00154   long decorations;
00155   long inputMode;
00156   long unknown;
00157 } wxMWM_Hints;
00158 
00159 /* bit definitions for MwmHints.decorations */
00160 #define MWM_DECOR_ALL           (1L << 0)
00161 #define MWM_DECOR_BORDER        (1L << 1)
00162 #define MWM_DECOR_RESIZEH       (1L << 2)
00163 #define MWM_DECOR_TITLE         (1L << 3)
00164 #define MWM_DECOR_MENU          (1L << 4)
00165 #define MWM_DECOR_MINIMIZE      (1L << 5)
00166 #define MWM_DECOR_MAXIMIZE      (1L << 6)
00167 
00168 Bool wxFrame::Create(wxFrame *frame_parent, char *title,
00169                    int x, int y, int width, int height,
00170                    int _style, char *name)
00171 {
00172     Widget parent_widget, wgt;
00173     wxChildList *tlf;
00174     Atom WM_DELETE_WINDOW;
00175 
00176     context = wxGetContextForFrame();
00177 
00178     // chain child <-> parent
00179     if ((parent = frame_parent)) {
00180       wxWindow_Xintern *ph;
00181       ph = frame_parent->GetHandle();
00182       parent_widget = ph->frame;
00183       parent->AddChild(this);
00184     } else {
00185        parent_widget = wxAPP_TOPLEVEL;
00186     }
00187     tlf = wxTopLevelFrames(this);
00188     tlf->Append(this);
00189     tlf->Show(this, FALSE);
00190 
00191     // create top level or transient shell
00192     if ( (style = _style) & wxTRANSIENT ) {
00193       // create transient shell with WM_TRANSIENT_FOR property
00194       wxWindow *p;
00195       Widget pw;
00196 
00197       for (p = parent; p; p = p->GetParent()) {
00198        if (wxSubType(p->__type, wxTYPE_FRAME)
00199            && !(p->GetWindowStyleFlag() & wxTRANSIENT)) // frame must not be transient
00200          break;
00201       }
00202       if (p) {
00203        wxWindow_Xintern *ph;
00204        ph = p->GetHandle();
00205        pw = ph->frame;
00206       } else
00207        pw = wxAPP_TOPLEVEL;
00208       X->frame = XtVaCreatePopupShell
00209        (name ? name : "shell", transientShellWidgetClass, parent_widget,
00210         XtNsaveUnder, FALSE,
00211         XtNtransientFor, pw,
00212         XtNvisual, wxAPP_VISUAL,
00213         XtNdepth, wx_visual_depth,
00214         XtNcolormap, wx_default_colormap,
00215         NULL);
00216     } else {
00217       // create top level shell
00218       X->frame = XtVaCreatePopupShell
00219        (name ? name : "shell", 
00220         (((style & wxFLOAT_FRAME)  && (style & wxNO_CAPTION))
00221          ? overrideShellWidgetClass 
00222          : topLevelShellWidgetClass), 
00223         parent_widget, 
00224         XtNvisual, wxAPP_VISUAL,
00225         XtNdepth, wx_visual_depth,
00226         XtNcolormap, wx_default_colormap,
00227         NULL);
00228     }
00229     // set common data
00230     SetSize(x, y, width, height, wxSIZE_AUTO | wxPOS_USE_MINUS_ONE);
00231     // create board widget
00232     wgt = XtVaCreateManagedWidget(
00233        name, xfwfBoardWidgetClass, X->frame,
00234        XtNhighlightThickness, 0,
00235        XtNbackground, wxGREY_PIXEL,
00236        NULL);
00237     X->handle = wgt;
00238     AddEventHandlers();
00239 
00240     XtRealizeWidget(X->frame);
00241     SetTitle(title);
00242     // make a WM_PROTOCOLS atom if necessary
00243     XInternAtom(XtDisplay(X->frame), "WM_PROTOCOLS", False);
00244     // make a WM_DELETE_WINDOW atom
00245     WM_DELETE_WINDOW = XInternAtom(XtDisplay(X->frame),
00246                                "WM_DELETE_WINDOW",
00247                                False);
00248     XSetWMProtocols(XtDisplay(X->frame),
00249                   XtWindow(X->frame),
00250                   &WM_DELETE_WINDOW,
00251                   1);
00252 
00253     /* part of show-&-hide fix */
00254     XtAddEventHandler(X->frame, StructureNotifyMask,
00255                     False, (XtEventHandler)wxFrameMapProc,
00256                     (XtPointer)saferef);
00257 
00258     cursor = wxSTANDARD_CURSOR;
00259 
00260     if (wxIsBusy())
00261       wxXSetBusyCursor(this, wxHOURGLASS_CURSOR);
00262 
00263     if ((_style & wxNO_RESIZE_BORDER)
00264        || (_style & wxNO_CAPTION)) {
00265       /* Copied off a newsgroup somewhere: */
00266       Atom WM_HINTS;
00267       Display *display;
00268       Window window;
00269 
00270       display = XtDisplay(X->frame);
00271       window = XtWindow(X->frame);
00272 
00273       /* First try to set MWM hints */
00274       WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", True);
00275       if ( WM_HINTS != None ) {
00276 #define MWM_HINTS_DECORATIONS (1L << 1)
00277        wxMWM_Hints MWMHints = { MWM_HINTS_DECORATIONS, 0, 0, 0, 0 };
00278        
00279        if (!(_style & wxNO_RESIZE_BORDER)
00280            || !(_style & wxNO_CAPTION))
00281          MWMHints.decorations |= MWM_DECOR_BORDER;
00282 
00283        if (!(_style & wxNO_RESIZE_BORDER))
00284          MWMHints.decorations |= (MWM_DECOR_RESIZEH
00285                                | MWM_DECOR_MINIMIZE
00286                                | MWM_DECOR_MAXIMIZE);
00287 
00288        if (!(_style & wxNO_CAPTION))
00289          MWMHints.decorations |= (MWM_DECOR_TITLE
00290                                | MWM_DECOR_MENU);
00291 
00292        XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
00293                      PropModeReplace, (unsigned char *)&MWMHints,
00294                      sizeof(MWMHints)/sizeof(long));
00295       }
00296       /* Now try to set KWM hints */
00297       if (_style & wxNO_CAPTION) {
00298        WM_HINTS = XInternAtom(display, "KWM_WIN_DECORATION", True);
00299        if ( WM_HINTS != None ) {
00300          long KWMHints = 0;
00301          
00302          if (!(_style & wxNO_RESIZE_BORDER))
00303            KWMHints = 2; /* tiny decoration */
00304          
00305          XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
00306                        PropModeReplace, (unsigned char *)&KWMHints,
00307                        sizeof(KWMHints)/sizeof(long));
00308        }
00309       }
00310       /* Now try to set GNOME hints */
00311       if ((_style & wxNO_RESIZE_BORDER)
00312          && (_style & wxNO_CAPTION)) {
00313        WM_HINTS = XInternAtom(display, "_WIN_HINTS", True);
00314        if (WM_HINTS != None) {
00315          long GNOMEHints = 0;
00316          
00317          XChangeProperty(display, window, WM_HINTS, XA_CARDINAL, 32,
00318                        PropModeReplace, (unsigned char *)&GNOMEHints,
00319                        sizeof(GNOMEHints)/sizeof(long));
00320        }
00321       }
00322     }
00323 
00324 
00325     if ((x > wxDEFAULT_POSITION) && (y > wxDEFAULT_POSITION)) {
00326       /* Tell the window manager that we really meant the initial position: */
00327       XSizeHints hints;
00328       hints.flags = USPosition;
00329       if ((width >= 0) && (height >= 0))
00330        hints.flags |= USSize;
00331       hints.x = x;
00332       hints.y = y;
00333       hints.width = width;
00334       hints.height = height;
00335       XSetWMNormalHints(XtDisplay(X->frame), XtWindow(X->frame), &hints);
00336     }
00337 
00338     if (!plt_mask) {
00339       plt_mask = XCreateBitmapFromData(wxAPP_DISPLAY, wxAPP_ROOT, plt_xbm, plt_width, plt_height);
00340     }
00341     if (!plt_icon) {
00342       XpmAttributes *xpm;
00343 #ifdef MZ_PRECISE_GC
00344       xpm = (XpmAttributes *)GC_malloc_atomic(sizeof(XpmAttributes));
00345 #else
00346       xpm = new WXGC_ATOMIC XpmAttributes;
00347 #endif
00348       xpm->valuemask = (XpmReturnInfos | XpmReturnPixels | XpmCloseness
00349                      | XpmVisual | XpmDepth | XpmColormap);
00350       xpm->closeness = 40000;
00351       xpm->visual = wxAPP_VISUAL;
00352       xpm->depth = wx_visual_depth;
00353       xpm->colormap = wx_default_colormap;
00354       if (XpmCreatePixmapFromData(wxAPP_DISPLAY, wxAPP_ROOT,
00355                               plt_xpm, &plt_icon,
00356                               (Pixmap*)NULL, xpm)
00357          != XpmSuccess)
00358        plt_icon = (Pixmap)NULL;
00359     }
00360 
00361     if ((style & wxTRANSIENT) && frame_parent) {
00362       /* Dialog: use parent frame's icon. */
00363       Pixmap icon, mask;
00364 
00365       XtVaGetValues(frame_parent->X->frame, 
00366                   XtNiconMask, &mask, 
00367                   XtNiconPixmap, &icon, NULL);
00368 
00369       if (mask && icon) {
00370        XtVaSetValues(X->frame, XtNiconMask, mask, NULL);
00371        XtVaSetValues(X->frame, XtNiconPixmap, icon, NULL);
00372       }
00373     } else {
00374       if (plt_mask && plt_icon) {
00375        XtVaSetValues(X->frame, XtNiconMask, plt_mask, NULL);
00376        XtVaSetValues(X->frame, XtNiconPixmap, plt_icon, NULL);
00377       }
00378     }
00379 
00380     /* Let window managers know that the frame can receive the focus
00381        (patch from Alexey Voinov): */
00382     XtVaSetValues(X->frame, XtNinput, True, NULL);
00383 
00384     return TRUE;
00385 }
00386 
00387 //-----------------------------------------------------------------------------
00388 // leave place for menubar and statusline
00389 //-----------------------------------------------------------------------------
00390 
00391 void wxFrame::GetSize(int *width, int *height)
00392 {
00393   if (X->frame && XtIsRealized(X->frame)) {
00394     /* Get the actual window size, insteda of waiting for events
00395        to update the widget */
00396     int x_pos, y_pos;
00397     unsigned int border, depth;
00398     Window root;
00399     Display *disp;
00400     Window win;
00401 
00402     disp = XtDisplay(X->frame);
00403     win = XtWindow(X->frame);
00404     
00405     XGetGeometry(disp, win,
00406                &root, &x_pos, &y_pos,
00407                (unsigned int *)width, (unsigned int *)height,
00408                &border, &depth);
00409   } else
00410     wxWindow::GetSize(width, height);
00411 
00412 }
00413 
00414 void wxFrame::GetPosition(int *x, int *y)
00415 {
00416   if (X->frame && XtIsRealized(X->frame)) {
00417     /* Get the actual window position, instead of waiting for events
00418        to update the widget */
00419     Display *disp;
00420     Window win;
00421     Window child;
00422 
00423     disp = XtDisplay(X->frame);
00424     win = XtWindow(X->frame);
00425 
00426     XTranslateCoordinates(disp, 
00427                        win, 
00428                        DefaultRootWindow(disp),
00429                        0, 0, 
00430                        x, y, &child);
00431   } else
00432     wxWindow::GetPosition(x, y);
00433 }
00434 
00435 void wxFrame::Fit(void)
00436 {
00437     int hsize=0, vsize=0;
00438 
00439     if (children) {
00440         wxChildNode *node;
00441        for (node = children->First(); node; node = node->Next()) {
00442            wxWindow *child;
00443            child = (wxWindow*)(node->Data());
00444            if (child) {
00445               // skip menubar and status line for computation
00446               int x, y, w, h;
00447               int i=0;
00448               for ( /* i=0 */; i<num_status; ++i) {
00449                 if (child == status[i])
00450                   break;
00451               }
00452               if (child == menubar || i < num_status) {
00453                 continue;
00454               }
00455               // compute maximal size
00456               child->GetPosition(&x, &y); child->GetSize(&w, &h);
00457               hsize = max(hsize, x + w);
00458               vsize = max(vsize, y + h);
00459            }
00460        }
00461        hsize -= xoff; vsize -= yoff;
00462     } else {
00463        hsize = PANEL_HMARGIN;
00464        vsize = PANEL_VMARGIN;
00465     }
00466     hsize += /* PANEL_HMARGIN + */ (style & wxBORDER ? 4 : 0 );
00467     vsize += /* PANEL_VMARGIN + */ (style & wxBORDER ? 4 : 0 );
00468     SetClientSize(hsize, vsize);
00469 }
00470 
00471 // void wxFrame::Layout(void)
00472 // --> wxLayout.cc
00473 
00474 void wxFrame::GetClientSize(int *width, int *height)
00475 {
00476     int dummy, h1=0, h2=0, i;
00477 
00478     GetSize(width, height);
00479     if (menubar)  menubar->GetSize(&dummy, &h1);   // get menubar's height
00480     for (i = 0; i < num_status; i++) {
00481       status[i]->GetSize(&dummy, &h2); // get status lines's height
00482       h1 += h2;
00483     }
00484     *height -= h1;                            // adjust height
00485 }
00486 
00487 void wxFrame::SetClientSize(int width, int height)
00488 {
00489     int dummy, h1=0, h2=0;
00490 
00491     if (menubar)  menubar->GetSize(&dummy, &h1);   // get menubar's height
00492     if (status)   status[0]->GetSize(&dummy, &h2); // get status lines's height
00493     height += h1 + h2;                                // adjust height
00494     wxWindow::SetClientSize(width, height);
00495 }
00496 
00497 void wxFrame::EnforceSize(int minw, int minh, int maxw, int maxh, int incw, int inch)
00498 {
00499   XSizeHints sh;
00500   int x, y;
00501 
00502   if (minw < 0)
00503     minw = 0;
00504   if (minh < 0)
00505     minh = 0;
00506   if (maxw < 0)
00507     maxw = 32000;
00508   if (maxh < 0)
00509     maxh = 32000;
00510 
00511   sh.flags = (PMinSize | PMaxSize | PResizeInc | USPosition);
00512   sh.min_width = minw;
00513   sh.min_height = minh;
00514   sh.max_width = maxw;
00515   sh.max_height = maxh;
00516   sh.width_inc = incw;
00517   sh.height_inc = inch;
00518 
00519   GetPosition(&x, &y);
00520   sh.x = x;
00521   sh.y = y;
00522 
00523   XSetWMNormalHints(XtDisplay(X->frame), 
00524                   XtWindow(X->frame),
00525                   &sh);
00526 }
00527 
00528 //-----------------------------------------------------------------------------
00529 // iconize, maximize
00530 //-----------------------------------------------------------------------------
00531 
00532 void wxFrame::Iconize(Bool iconize)
00533 {
00534   if (!IsShown())
00535     return;
00536   
00537   if (iconize) {
00538     XIconifyWindow(XtDisplay(X->frame), 
00539                  XtWindow(X->frame), 
00540                  XScreenNumberOfScreen(XtScreen(X->frame)));
00541   } else {
00542     XtMapWidget(X->frame);
00543   }
00544 }
00545 
00546 Bool wxFrame::Iconized(void)
00547 {
00548   XWindowAttributes wa;
00549 
00550   if (!IsShown())
00551     return FALSE;
00552 
00553   XSync(XtDisplay(X->frame), FALSE);
00554 
00555   XGetWindowAttributes(XtDisplay(X->frame), XtWindow(X->frame), &wa);
00556 
00557   return (wa.map_state == IsUnmapped);
00558 }
00559 
00560 void wxFrame::Maximize(Bool WXUNUSED(maximize))
00561 {
00562 }
00563 
00564 Bool wxFrame::IsMaximized()
00565 {
00566   return FALSE;
00567 }
00568 
00569 //-----------------------------------------------------------------------------
00570 // status line
00571 //-----------------------------------------------------------------------------
00572 
00573 void wxFrame::CreateStatusLine(int number, char *)
00574 {
00575     if (StatusLineExists())
00576        return;
00577 
00578     status = new WXGC_PTRS wxMessage* [num_status = min(number, wxMAX_STATUS)];
00579     for (int i = 0; i < num_status; ++i) {
00580        wxLayoutConstraints *constr;
00581        int ww, hh;
00582        wxMessage *sm;
00583        wxWindow **sr;
00584 
00585        sm = DEBUG_NEW wxMessage(this, "", 0, 0, wxBORDER, NULL, "status");
00586        status[i] = sm;
00587        sm->AllowResize(FALSE);
00588        sm->SetAlignment(wxALIGN_LEFT);
00589        sm->GetSize(&ww, &hh);
00590        constr = DEBUG_NEW wxLayoutConstraints;
00591        sr = GetWinSafeRef();
00592        wxLC_MEM(constr->left, PercentOf(sr, wxWidth, i*(100/num_status)));
00593        wxLC_MEM(constr->top, Below(sr, 0)); // wxBottom of client area
00594        wxLC_MEM(constr->height, Absolute(hh));
00595        if (i != num_status-1) {
00596          wxLC_MEM(constr->width, PercentOf(sr, wxWidth, 100 / num_status));
00597        } else {
00598          wxLC_MEM(constr->right, SameAs(sr, wxRight, 0));
00599          wxLC_MEM(constr->width, Unconstrained());
00600        }
00601        status[i]->SetConstraints(constr);
00602 
00603     }
00604 
00605     Layout();
00606 }
00607 
00608 void wxFrame::SetStatusText(char *text, int number)
00609 {
00610     if (number < num_status)
00611        status[number]->SetLabel(text ? text : (char *)"");
00612 }
00613 
00614 Bool wxFrame::StatusLineExists(void)
00615 {
00616     return (num_status != 0);
00617 }
00618 
00619 //-----------------------------------------------------------------------------
00620 // associated GDI objects
00621 //-----------------------------------------------------------------------------
00622 
00623 wxMenuBar *wxFrame::GetMenuBar(void)
00624 {
00625     return menubar;
00626 }
00627 
00628 void wxFrame::SetIcon(wxBitmap *icon, wxBitmap *mask, int kind)
00629 {
00630   if (kind == 2) /* large */
00631     return;
00632 
00633   if (icon->Ok()) {
00634     wxBitmap *bm;
00635     int w, h;
00636 
00637     w = icon->GetWidth();
00638     h = icon->GetHeight();
00639     bm = new wxBitmap(w, h);
00640     if (bm->Ok()) {
00641       wxMemoryDC *mdc;
00642       Pixmap pm;
00643 
00644       mdc = new wxMemoryDC();
00645       mdc->SelectObject(bm);
00646       mdc->Blit(0, 0, w, h, icon, 0, 0, wxSTIPPLE, NULL);
00647       mdc->SelectObject(NULL);
00648 
00649       if (mask && !mask->Ok())
00650        mask = NULL;
00651       
00652       pm = mask ? GETPIXMAP(mask) : (Pixmap)NULL;
00653       XtVaSetValues(X->frame, XtNiconMask, pm, NULL);
00654       pm = GETPIXMAP(bm);
00655       XtVaSetValues(X->frame, XtNiconPixmap, pm, (Pixmap)NULL, NULL);
00656       
00657       frame_icon = bm;
00658       frame_mask = mask;
00659     }
00660   }
00661 }
00662 
00663 void wxFrame::SetMenuBar(wxMenuBar *new_menubar)
00664 {
00665   /* MATTHEW: Enforce safety */
00666   if (new_menubar && new_menubar->GetParent())
00667     return;
00668 
00669   if (menubar)
00670     menubar->Destroy();     // destroy X internal representation
00671   if ((menubar = new_menubar)) {
00672     int ww, hh;
00673     
00674     menubar->Create(this);
00675     menubar->GetSize(&ww, &hh);
00676     yoff = hh; // offset off client area inside frame
00677   }
00678 }
00679 
00680 //-----------------------------------------------------------------------------
00681 // miscellaneous
00682 //-----------------------------------------------------------------------------
00683 
00684 void wxFrame::Command(int id)
00685 {
00686   OnMenuCommand(id);
00687 }
00688 
00689 static void ForceFocus(Widget frame)
00690 {
00691   static int force_focus = 0;
00692 
00693   if (!force_focus) {
00694     if (!wxGetBoolPreference("forceFocus", &force_focus))
00695       force_focus = 0;
00696     force_focus = !force_focus ? -1 : 1;
00697   }
00698 
00699   if (force_focus > 0) {
00700     Window current;
00701     int old_revert;
00702     XGetInputFocus(XtDisplay(frame), &current, &old_revert);
00703     if (current != PointerRoot) {
00704       XWindowAttributes attrib;
00705 
00706       XFlush(XtDisplay(frame));
00707       XGrabServer(XtDisplay(frame));
00708       
00709       /* Sleep for corce_focus usecs: */
00710       {
00711        struct timeval time;
00712        if (force_focus > 1000)
00713          force_focus = 999;
00714 
00715        time.tv_sec = 0;
00716        time.tv_usec = force_focus;
00717        select(0, NULL, NULL, NULL, &time);
00718       }
00719 
00720       XGetWindowAttributes(XtDisplay(frame), XtWindow(frame), &attrib);
00721       if (attrib.map_state == IsViewable)
00722        XSetInputFocus(XtDisplay(frame), XtWindow(frame),
00723                      RevertToNone, CurrentTime);
00724     }
00725     XUngrabServer(XtDisplay(frame));
00726   }
00727 }
00728 
00729 extern "C" long scheme_get_milliseconds(void);
00730 
00731 Bool wxFrame::Show(Bool show)
00732 {
00733   wxChildList *tlf;
00734   
00735   if (show == IsShown()) { // do nothing if state doesn't change
00736     if (show) {
00737       wxUnpopMenu();
00738       /* Make sure window isn't iconized: */
00739       Iconize(FALSE);
00740       XRaiseWindow(XtDisplay(X->frame), XtWindow(X->frame));             
00741       ForceFocus(X->frame);      
00742     }
00743     return TRUE;
00744   }
00745 
00746   tlf = wxTopLevelFrames(this);
00747   tlf->Show(this, show);
00748   if (parent) {
00749     wxChildList *cl;
00750     cl = parent->GetChildren();
00751     cl->Show(this, show);
00752   }
00753   
00754   SetShown(show);
00755   if (show) {
00756     wxUnpopMenu();
00757     XtMapWidget(X->frame);
00758     XRaiseWindow(XtDisplay(X->frame), XtWindow(X->frame));
00759     ForceFocus(X->frame);
00760     last_shown_time = scheme_get_milliseconds();
00761   } else {
00762     /* XWithdrawWindow tells the window manager to get rid of icons
00763        for iconified windows. Unfortunately, it also destroys the
00764        window under some (unknown) circumstances with CTWM - which is
00765        what I like to use. If we have waited a little while, CTWM
00766        seems happy. Solution: just don't call XWidthdrawWindow if the
00767        window was shown recently - the user hasn't had time to iconize
00768        it, anyway. */
00769     if (last_shown_time + 1000 < scheme_get_milliseconds())
00770       XWithdrawWindow(XtDisplay(X->frame), XtWindow(X->frame), XScreenNumberOfScreen(XtScreen(X->frame)));
00771     XtUnmapWidget(X->frame);
00772   }
00773 
00774   XFlush(XtDisplay(X->frame));
00775   XSync(XtDisplay(X->frame), FALSE);
00776 
00777   return TRUE;
00778 }
00779 
00780 void wxFrame::SetFrameModified(Bool mod)
00781 {
00782   if (!!show_as_mod != !!mod) {
00783     char *t;
00784     t = GetTitle();
00785     t = copystring(t);
00786     show_as_mod = mod;
00787     SetTitle(t);
00788   }
00789 }
00790 
00791 char *wxFrame::GetTitle(void)
00792 {
00793   char *t;
00794   t = wxWindow::GetTitle();
00795   if (t && show_as_mod) {
00796     int len;
00797     len = strlen(t);
00798     /* Double-check for asterisk: */
00799     if (len && t[len-1] == '*') {
00800       char *s;
00801       s = copystring(t);
00802       s[len-1] = 0;
00803       t = s;
00804     }
00805   }
00806   return t;
00807 }
00808 
00809 void wxFrame::SetTitle(char *title)
00810 {
00811   if (show_as_mod && title) {
00812     int len;
00813     char *s;
00814     len = strlen(title);
00815     s = new WXGC_ATOMIC char[len + 2];
00816     memcpy(s, title, len);
00817     s[len] = '*';
00818     s[len+1] = 0;
00819     title = s;
00820   }
00821   wxWindow::SetTitle(title);
00822 }
00823 
00824 
00825 //-----------------------------------------------------------------------------
00826 // virtual event functions
00827 //-----------------------------------------------------------------------------
00828 
00829 void wxFrame::OnMenuSelect(long id)
00830 {
00831   SetStatusText(menubar->GetHelpString(id));
00832 }
00833 
00834 void wxFrame::OnMenuClick()
00835 {
00836 }
00837 
00838 void wxFrame::OnToolbarButton()
00839 {
00840 }
00841 
00842 void wxFrame::OnMDIActivate(Bool WXUNUSED(flag))
00843 {
00844 }