/** \file * \brief IupDialog class * * See Copyright Notice in "iup.h" */ #include #include #include #include #include #include #include #include #include #include #include #include "iup.h" #include "iupcbs.h" #include "iup_class.h" #include "iup_object.h" #include "iup_childtree.h" #include "iup_dlglist.h" #include "iup_attrib.h" #include "iup_drv.h" #include "iup_drvfont.h" #include "iup_drvinfo.h" #include "iup_focus.h" #include "iup_str.h" #define _IUPDLG_PRIVATE #include "iup_dialog.h" #include "iup_image.h" #include "iupmot_drv.h" #include "iupmot_color.h" Atom iupmot_wm_deletewindow = 0; /* used also by IupMessageDlg */ static int motDialogSetBgColorAttrib(Ihandle* ih, const char* value); /**************************************************************** Utilities ****************************************************************/ int iupdrvDialogIsVisible(Ihandle* ih) { return iupdrvIsVisible(ih) || ih->data->show_state == IUP_MINIMIZE; } void iupdrvDialogUpdateSize(Ihandle* ih) { Dimension width, height; XtVaGetValues(ih->handle, XmNwidth, &width, XmNheight, &height, NULL); ih->currentwidth = width; ih->currentheight = height; } void iupdrvDialogGetSize(InativeHandle* handle, int *w, int *h) { Dimension width, height; XtVaGetValues(handle, XmNwidth, &width, XmNheight, &height, NULL); if (w) *w = width; if (h) *h = height; } void iupmotDialogSetVisual(Ihandle* ih, void* visual) { Ihandle *dialog = IupGetDialog(ih); XtVaSetValues(dialog->handle, XmNvisual, visual, NULL); } void iupmotDialogResetVisual(Ihandle* ih) { Ihandle *dialog = IupGetDialog(ih); XtVaSetValues(dialog->handle, XmNvisual, iupmot_visual, NULL); } void iupdrvDialogSetVisible(Ihandle* ih, int visible) { if (visible) { XtMapWidget(ih->handle); XRaiseWindow(iupmot_display, XtWindow(ih->handle)); while (!iupdrvDialogIsVisible(ih)); /* waits until window get mapped */ } else { /* if iupdrvIsVisible reports hidden, then it should be minimized */ if (!iupdrvIsVisible(ih)) /* can NOT hide a minimized window, so map it first. */ { XtMapWidget(ih->handle); XRaiseWindow(iupmot_display, XtWindow(ih->handle)); while (!iupdrvDialogIsVisible(ih)); /* waits until window get mapped */ } XtUnmapWidget(ih->handle); while (iupdrvDialogIsVisible(ih)); /* waits until window gets unmapped */ } } void iupdrvDialogGetPosition(InativeHandle* handle, int *x, int *y) { Dimension cur_x, cur_y; XtVaGetValues(handle, XmNx, &cur_x, XmNy, &cur_y, NULL); if (x) *x = cur_x; if (y) *y = cur_y; } void iupdrvDialogSetPosition(Ihandle *ih, int x, int y) { XtVaSetValues(ih->handle, XmNx, (XtArgVal)x, XmNy, (XtArgVal)y, NULL); } static int motDialogGetMenuSize(Ihandle* ih) { if (ih->data->menu) return iupdrvMenuGetMenuBarSize(ih->data->menu); else return 0; } void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu) { static int native_border = 0; static int native_caption = 0; int has_caption = iupAttribGetBoolean(ih, "MAXBOX") || iupAttribGetBoolean(ih, "MINBOX") || iupAttribGetBoolean(ih, "MENUBOX") || IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */ int has_border = has_caption || iupAttribGetBoolean(ih, "RESIZE") || iupAttribGetBoolean(ih, "BORDER"); *menu = motDialogGetMenuSize(ih); if (ih->handle && iupdrvDialogIsVisible(ih)) { int win_border, win_caption; if (iupdrvGetWindowDecor((void*)XtWindow(ih->handle), &win_border, &win_caption)) { *border = 0; if (has_border) *border = win_border; *caption = 0; if (has_caption) *caption = win_caption; if (!native_border && *border) native_border = win_border; if (!native_caption && *caption) native_caption = win_caption; return; } } /* I could not set the size of the window including the decorations when the dialog is hidden */ /* So we have to estimate the size of borders and caption when the dialog is hidden */ *border = 0; if (has_border) { if (native_border) *border = native_border; else *border = 5; } *caption = 0; if (has_caption) { if (native_caption) *caption = native_caption; else *caption = 20; } } static int motDialogQueryWMspecSupport(Atom feature) { static Atom netsuppport = 0; Atom type; Atom *atoms; int format; unsigned long after, natoms, i; if (!netsuppport) netsuppport = XmInternAtom(iupmot_display, "_NET_SUPPORTED", False); /* get all the features */ XGetWindowProperty(iupmot_display, RootWindow(iupmot_display, iupmot_screen), netsuppport, 0, LONG_MAX, False, XA_ATOM, &type, &format, &natoms, &after, (unsigned char **)&atoms); if (type != XA_ATOM || atoms == NULL) { if (atoms) XFree(atoms); return 0; } /* Lookup the feature we want */ for (i = 0; i < natoms; i++) { if (atoms[i] == feature) { XFree(atoms); return 1; } } XFree(atoms); return 0; } static void motDialogSetWindowManagerStyle(Ihandle* ih) { MwmHints hints; static Atom xwmhint = 0; if (!xwmhint) xwmhint = XmInternAtom(iupmot_display, "_MOTIF_WM_HINTS", False); hints.flags = (MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS); hints.functions = 0; hints.decorations = 0; hints.input_mode = 0; hints.status = 0; if (IupGetAttribute(ih, "TITLE")) { /* must use IupGetAttribute to check from the native implementation */ hints.functions |= MWM_FUNC_MOVE; hints.decorations |= MWM_DECOR_TITLE; } if (iupAttribGetBoolean(ih, "MENUBOX")) { hints.functions |= MWM_FUNC_CLOSE; hints.decorations |= MWM_DECOR_MENU; } if (iupAttribGetBoolean(ih, "MINBOX")) { hints.functions |= MWM_FUNC_MINIMIZE; hints.decorations |= MWM_DECOR_MINIMIZE; } if (iupAttribGetBoolean(ih, "MAXBOX")) { hints.functions |= MWM_FUNC_MAXIMIZE; hints.decorations |= MWM_DECOR_MAXIMIZE; } if (iupAttribGetBoolean(ih, "RESIZE")) { hints.functions |= MWM_FUNC_RESIZE; hints.decorations |= MWM_DECOR_RESIZEH; } if (iupAttribGetBoolean(ih, "BORDER")) hints.decorations |= MWM_DECOR_BORDER; XChangeProperty(iupmot_display, XtWindow(ih->handle), xwmhint, xwmhint, 32, PropModeReplace, (const unsigned char *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS); } static void motDialogChangeWMState(Ihandle* ih, Atom state1, Atom state2, int operation) { static Atom wmstate = 0; if (!wmstate) wmstate = XmInternAtom(iupmot_display, "_NET_WM_STATE", False); if (iupdrvDialogIsVisible(ih)) { XEvent evt; evt.type = ClientMessage; evt.xclient.type = ClientMessage; evt.xclient.serial = 0; evt.xclient.send_event = True; evt.xclient.display = iupmot_display; evt.xclient.window = XtWindow(ih->handle); evt.xclient.message_type = wmstate; evt.xclient.format = 32; evt.xclient.data.l[0] = operation; evt.xclient.data.l[1] = state1; evt.xclient.data.l[2] = state2; evt.xclient.data.l[3] = 0; evt.xclient.data.l[4] = 0; XSendEvent(iupmot_display, RootWindow(iupmot_display, iupmot_screen), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt); } else { if (operation) { if (state1 && state2) { Atom atoms[2]; atoms[0] = state1; atoms[0] = state2; XChangeProperty(iupmot_display, XtWindow(ih->handle), wmstate, XA_ATOM, 32, PropModeReplace, (const unsigned char *)&atoms, 2); } else { XChangeProperty(iupmot_display, XtWindow(ih->handle), wmstate, XA_ATOM, 32, PropModeReplace, (const unsigned char *)&state1, 1); } } else { /* TODO: This is not working. The property is not correctly removed. */ /* XDeleteProperty(iupmot_display, XtWindow(ih->handle), wmstate); */ /* Maybe the right way to do it is to retrieve all the atoms */ /* and change again with all atoms except the one to remove */ } } } static int motDialogSetFullScreen(Ihandle* ih, int fullscreen) { static int support_fullscreen = -1; /* WARNING: The WM can be changed dinamically */ static Atom xwmfs = 0; if (!xwmfs) xwmfs = XmInternAtom(iupmot_display, "_NET_WM_STATE_FULLSCREEN", False); if (support_fullscreen == -1) support_fullscreen = motDialogQueryWMspecSupport(xwmfs); if (support_fullscreen) { motDialogChangeWMState(ih, xwmfs, 0, fullscreen); return 1; } return 0; } int iupdrvDialogSetPlacement(Ihandle* ih) { char* placement; ih->data->show_state = IUP_SHOW; if (iupAttribGetBoolean(ih, "FULLSCREEN")) return 1; placement = iupAttribGet(ih, "PLACEMENT"); if (!placement) return 0; if (iupStrEqualNoCase(placement, "MINIMIZED")) { if (iupdrvDialogIsVisible(ih)) XIconifyWindow(iupmot_display, XtWindow(ih->handle), iupmot_screen); else { /* TODO: This is not working, so force a minimize after visible. */ /*XWMHints wm_hints; */ /*wm_hints.flags = StateHint; */ /*wm_hints.initial_state = IconicState; */ /*XSetWMHints(iupmot_display, XtWindow(ih->handle), &wm_hints); */ XtMapWidget(ih->handle); XIconifyWindow(iupmot_display, XtWindow(ih->handle), iupmot_screen); } } else if (iupStrEqualNoCase(placement, "MAXIMIZED")) { static Atom maxatoms[2] = {0, 0}; if (!(maxatoms[0])) { maxatoms[0] = XmInternAtom(iupmot_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); maxatoms[1] = XmInternAtom(iupmot_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); } motDialogChangeWMState(ih, maxatoms[0], maxatoms[1], 1); } else if (iupStrEqualNoCase(placement, "FULL")) { int width, height, x, y; int border, caption, menu; iupdrvDialogGetDecoration(ih, &border, &caption, &menu); /* position the decoration outside the screen */ x = -(border); y = -(border+caption+menu); /* the dialog client area will cover the task bar */ iupdrvGetFullSize(&width, &height); height += menu; /* the menu is included in the client area size in Motif. */ /* set the new size and position */ /* The resize event will update the layout */ XtVaSetValues(ih->handle, XmNx, (XtArgVal)x, /* outside border */ XmNy, (XtArgVal)y, XmNwidth, (XtArgVal)width, /* client size */ XmNheight, (XtArgVal)height, NULL); } iupAttribSetStr(ih, "PLACEMENT", NULL); /* reset to NORMAL */ return 1; } /**************************************************************************** Attributes ****************************************************************************/ static int motDialogSetMinSizeAttrib(Ihandle* ih, const char* value) { int decorwidth = 0, decorheight = 0; int min_w = 1, min_h = 1; /* MINSIZE default value */ iupStrToIntInt(value, &min_w, &min_h, 'x'); /* The minmax size restricts the client area */ iupDialogGetDecorSize(ih, &decorwidth, &decorheight); if (min_w > decorwidth) XtVaSetValues(ih->handle, XmNminWidth, min_w-decorwidth, NULL); if (min_h > decorheight) XtVaSetValues(ih->handle, XmNminHeight, min_h-decorheight, NULL); return 1; } static int motDialogSetMaxSizeAttrib(Ihandle* ih, const char* value) { int decorwidth = 0, decorheight = 0; int max_w = 65535, max_h = 65535; /* MAXSIZE default value */ iupStrToIntInt(value, &max_w, &max_h, 'x'); /* The minmax size restricts the client area */ iupDialogGetDecorSize(ih, &decorwidth, &decorheight); if (max_w > decorwidth) XtVaSetValues(ih->handle, XmNmaxWidth, max_w-decorwidth, NULL); if (max_h > decorheight) XtVaSetValues(ih->handle, XmNmaxHeight, max_h-decorheight, NULL); return 1; } static char* motDialogGetXAttrib(Ihandle *ih) { char* str = iupStrGetMemory(20); int x; iupdrvDialogGetPosition(ih->handle, &x, NULL); sprintf(str, "%d", x); return str; } static char* motDialogGetYAttrib(Ihandle *ih) { char* str = iupStrGetMemory(20); int y; iupdrvDialogGetPosition(ih->handle, &y, NULL); sprintf(str, "%d", y); return str; } static int motDialogSetTitleAttrib(Ihandle* ih, const char* value) { if (!value) value = ""; XtVaSetValues(ih->handle, XmNtitle, value, XmNiconName, value, NULL); return 0; } static char* motDialogGetTitleAttrib(Ihandle* ih) { char* title; XtVaGetValues(ih->handle, XmNtitle, &title, NULL); if (!title || title[0] == 0) return NULL; else { char* str = iupStrGetMemory(200); strcpy(str, title); return str; } } static char* motDialogGetClientSizeAttrib(Ihandle *ih) { char* str = iupStrGetMemory(20); Dimension manager_width, manager_height; Widget dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager"); XtVaGetValues(dialog_manager, XmNwidth, &manager_width, XmNheight, &manager_height, NULL); sprintf(str, "%dx%d", (int)manager_width, (int)manager_height - motDialogGetMenuSize(ih)); return str; } static int motDialogSetBgColorAttrib(Ihandle* ih, const char* value) { Pixel color = iupmotColorGetPixelStr(value); if (color != (Pixel)-1) { Widget dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager"); XtVaSetValues(dialog_manager, XmNbackground, color, NULL); XtVaSetValues(dialog_manager, XmNbackgroundPixmap, XmUNSPECIFIED_PIXMAP, NULL); return 1; } return 0; } static int motDialogSetBackgroundAttrib(Ihandle* ih, const char* value) { if (motDialogSetBgColorAttrib(ih, value)) return 1; else { Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0); if (pixmap) { Widget dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager"); XtVaSetValues(dialog_manager, XmNbackgroundPixmap, pixmap, NULL); return 1; } } return 0; } static int motDialogSetFullScreenAttrib(Ihandle* ih, const char* value) { if (iupStrBoolean(value)) { if (!iupAttribGet(ih, "_IUPMOT_FS_STYLE")) { int visible = iupdrvDialogIsVisible(ih); if (visible) iupAttribSetStr(ih, "_IUPMOT_FS_STYLE", "VISIBLE"); else iupAttribSetStr(ih, "_IUPMOT_FS_STYLE", "HIDDEN"); /* save the previous decoration attributes */ /* during fullscreen these attributes can be consulted by the application */ iupAttribStoreStr(ih, "_IUPMOT_FS_MAXBOX", iupAttribGet(ih, "MAXBOX")); iupAttribStoreStr(ih, "_IUPMOT_FS_MINBOX", iupAttribGet(ih, "MINBOX")); iupAttribStoreStr(ih, "_IUPMOT_FS_MENUBOX",iupAttribGet(ih, "MENUBOX")); iupAttribStoreStr(ih, "_IUPMOT_FS_RESIZE", iupAttribGet(ih, "RESIZE")); iupAttribStoreStr(ih, "_IUPMOT_FS_BORDER", iupAttribGet(ih, "BORDER")); iupAttribStoreStr(ih, "_IUPMOT_FS_TITLE", IupGetAttribute(ih, "TITLE")); /* must use IupGetAttribute to check from the native implementation */ /* remove the decorations attributes */ iupAttribSetStr(ih, "MAXBOX", "NO"); iupAttribSetStr(ih, "MINBOX", "NO"); iupAttribSetStr(ih, "MENUBOX", "NO"); IupSetAttribute(ih, "TITLE", NULL); iupAttribSetStr(ih, "TITLE", NULL); /* remove from the hash table if we are during IupMap */ iupAttribSetStr(ih, "RESIZE", "NO"); iupAttribSetStr(ih, "BORDER", "NO"); /* use WM fullscreen support */ if (!motDialogSetFullScreen(ih, 1)) { /* or configure fullscreen manually */ int decor; int width, height; /* hide before changing decorations */ if (visible) { iupAttribSetStr(ih, "_IUPMOT_SHOW_STATE", NULL); /* To avoid a SHOW_CB notification */ XtUnmapWidget(ih->handle); } /* save the previous position and size */ iupAttribStoreStr(ih, "_IUPMOT_FS_X", IupGetAttribute(ih, "X")); /* must use IupGetAttribute to check from the native implementation */ iupAttribStoreStr(ih, "_IUPMOT_FS_Y", IupGetAttribute(ih, "Y")); iupAttribStoreStr(ih, "_IUPMOT_FS_SIZE", IupGetAttribute(ih, "RASTERSIZE")); /* save the previous decoration */ XtVaGetValues(ih->handle, XmNmwmDecorations, &decor, NULL); iupAttribSetStr(ih, "_IUPMOT_FS_DECOR", (char*)decor); /* remove the decorations */ XtVaSetValues(ih->handle, XmNmwmDecorations, (XtArgVal)0, NULL); motDialogSetWindowManagerStyle(ih); /* get full screen size */ iupdrvGetFullSize(&width, &height); /* set position and size */ XtVaSetValues(ih->handle, XmNwidth, (XtArgVal)width, XmNheight, (XtArgVal)height, XmNx, (XtArgVal)0, XmNy, (XtArgVal)0, NULL); /* layout will be updated in motDialogConfigureNotify */ if (visible) XtMapWidget(ih->handle); } } } else { char* fs_style = iupAttribGet(ih, "_IUPMOT_FS_STYLE"); if (fs_style) { /* can only switch back from full screen if window was visible */ /* when fullscreen was set */ if (iupStrEqualNoCase(fs_style, "VISIBLE")) { iupAttribSetStr(ih, "_IUPMOT_FS_STYLE", NULL); /* restore the decorations attributes */ iupAttribStoreStr(ih, "MAXBOX", iupAttribGet(ih, "_IUPMOT_FS_MAXBOX")); iupAttribStoreStr(ih, "MINBOX", iupAttribGet(ih, "_IUPMOT_FS_MINBOX")); iupAttribStoreStr(ih, "MENUBOX",iupAttribGet(ih, "_IUPMOT_FS_MENUBOX")); IupSetAttribute(ih, "TITLE", iupAttribGet(ih, "_IUPMOT_FS_TITLE")); /* TITLE is not stored in the HashTable */ iupAttribStoreStr(ih, "RESIZE", iupAttribGet(ih, "_IUPMOT_FS_RESIZE")); iupAttribStoreStr(ih, "BORDER", iupAttribGet(ih, "_IUPMOT_FS_BORDER")); if (!motDialogSetFullScreen(ih, 0)) { int border, caption, menu, x, y; int visible = iupdrvDialogIsVisible(ih); if (visible) XtUnmapWidget(ih->handle); /* restore the decorations */ XtVaSetValues(ih->handle, XmNmwmDecorations, (XtArgVal)(int)iupAttribGet(ih, "_IUPMOT_FS_DECOR"), NULL); motDialogSetWindowManagerStyle(ih); /* the dialog decoration will not be considered yet in the next XtVaSetValues */ /* so compensate the decoration when restoring the position and size */ iupdrvDialogGetDecoration(ih, &border, &caption, &menu); x = iupAttribGetInt(ih, "_IUPMOT_FS_X") - (border); y = iupAttribGetInt(ih, "_IUPMOT_FS_Y") - (border+caption+menu); /* restore position and size */ XtVaSetValues(ih->handle, XmNx, (XtArgVal)x, XmNy, (XtArgVal)y, XmNwidth, (XtArgVal)(IupGetInt(ih, "_IUPMOT_FS_SIZE") - (2*border)), XmNheight, (XtArgVal)(IupGetInt2(ih, "_IUPMOT_FS_SIZE") - (2*border+caption)), NULL); /* layout will be updated in motDialogConfigureNotify */ if (visible) XtMapWidget(ih->handle); /* remove auxiliar attributes */ iupAttribSetStr(ih, "_IUPMOT_FS_X", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_Y", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_SIZE", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_DECOR", NULL); } /* remove auxiliar attributes */ iupAttribSetStr(ih, "_IUPMOT_FS_MAXBOX", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_MINBOX", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_MENUBOX",NULL); iupAttribSetStr(ih, "_IUPMOT_FS_RESIZE", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_BORDER", NULL); iupAttribSetStr(ih, "_IUPMOT_FS_TITLE", NULL); } } } return 1; } static int motDialogSetIconAttrib(Ihandle* ih, const char *value) { if (!value) XtVaSetValues(ih->handle, XmNiconPixmap, NULL, NULL); else { Pixmap icon = (Pixmap)iupImageGetIcon(value); Pixmap icon_mask = (Pixmap)iupImageGetMask(value); if (icon) XtVaSetValues(ih->handle, XmNiconPixmap, icon, NULL); if (icon_mask) XtVaSetValues(ih->handle, XmNiconMask, icon, NULL); } return 1; } /**************************************************************** Callbacks and Events ****************************************************************/ static void motDialogCBclose(Widget w, XtPointer client_data, XtPointer call_data) { Icallback cb; Ihandle *ih = (Ihandle*)client_data; if (!ih) return; (void)call_data; (void)w; /* even when ACTIVE=NO the dialog gets this event */ if (!iupdrvIsActive(ih)) return; cb = IupGetCallback(ih, "CLOSE_CB"); if (cb) { int ret = cb(ih); if (ret == IUP_IGNORE) return; if (ret == IUP_CLOSE) IupExitLoop(); } IupHide(ih); /* default: close the window */ } static void motDialogConfigureNotify(Widget w, XEvent *evt, String* s, Cardinal *card) { IFnii cb; int border, caption, menu; XConfigureEvent *cevent = (XConfigureEvent *)evt; Ihandle* ih; (void)s; (void)card; XtVaGetValues(w, XmNuserData, &ih, NULL); if (!ih) return; if (ih->data->menu && ih->data->menu->handle) { XtVaSetValues(ih->data->menu->handle, XmNwidth, (XtArgVal)(cevent->width), NULL); } if (ih->data->ignore_resize) return; iupdrvDialogGetDecoration(ih, &border, &caption, &menu); /* update dialog size */ ih->currentwidth = cevent->width + 2*border; ih->currentheight = cevent->height + 2*border + caption; /* menu is inside the dialog_manager */ cb = (IFnii)IupGetCallback(ih, "RESIZE_CB"); if (!cb || cb(ih, cevent->width, cevent->height - menu)!=IUP_IGNORE) /* width and height here are for the client area */ { ih->data->ignore_resize = 1; IupRefresh(ih); ih->data->ignore_resize = 0; } } static void motDialogCBStructureNotifyEvent(Widget w, XtPointer data, XEvent *evt, Boolean *cont) { Ihandle *ih = (Ihandle*)data; int state = -1; (void)cont; (void)w; switch(evt->type) { case MapNotify: { if (ih->data->show_state == IUP_MINIMIZE) /* it is a RESTORE. */ state = IUP_RESTORE; break; } case UnmapNotify: { if (ih->data->show_state != IUP_HIDE) /* it is a MINIMIZE. */ state = IUP_MINIMIZE; break; } } if (state < 0) return; if (ih->data->show_state != state) { IFni cb; ih->data->show_state = state; cb = (IFni)IupGetCallback(ih, "SHOW_CB"); if (cb && cb(ih, state) == IUP_CLOSE) IupExitLoop(); } } static void motDialogDestroyCallback(Widget w, Ihandle *ih, XtPointer call_data) { /* If the IUP dialog was not destroyed, destroy it here. */ if (iupObjectCheck(ih)) IupDestroy(ih); /* this callback is usefull to destroy children dialogs when the parent is destroyed. */ /* The application is responsable for destroying the children before this happen. */ (void)w; (void)call_data; } /**************************************************************** Idialog ****************************************************************/ /* replace the common dialog SetChildrenPosition method because of the menu that it is inside the dialog. */ static void motDialogSetChildrenPositionMethod(Ihandle* ih, int x, int y) { int menu_h = motDialogGetMenuSize(ih); (void)x; (void)y; /* Child coordinates are relative to client left-top corner. */ iupBaseSetPosition(ih->firstchild, 0, menu_h); } static void* motDialogGetInnerNativeContainerHandleMethod(Ihandle* ih, Ihandle* child) { (void)child; return XtNameToWidget(ih->handle, "*dialog_manager"); } static int motDialogMapMethod(Ihandle* ih) { Widget dialog_manager; InativeHandle* parent; int mwm_decor = 0; int num_args = 0; Arg args[20]; if (iupAttribGetBoolean(ih, "DIALOGFRAME")) { iupAttribSetStr(ih, "RESIZE", "NO"); iupAttribSetStr(ih, "MAXBOX", "NO"); iupAttribSetStr(ih, "MINBOX", "NO"); } /****************************/ /* Create the dialog shell */ /****************************/ if (iupAttribGet(ih, "TITLE")) mwm_decor |= MWM_DECOR_TITLE; if (iupAttribGetBoolean(ih, "MENUBOX")) mwm_decor |= MWM_DECOR_MENU; if (iupAttribGetBoolean(ih, "MINBOX")) mwm_decor |= MWM_DECOR_MINIMIZE; if (iupAttribGetBoolean(ih, "MAXBOX")) mwm_decor |= MWM_DECOR_MAXIMIZE; if (iupAttribGetBoolean(ih, "RESIZE")) mwm_decor |= MWM_DECOR_RESIZEH; if (iupAttribGetBoolean(ih, "BORDER")) mwm_decor |= MWM_DECOR_BORDER; iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* so XtRealizeWidget will not show the dialog */ iupmotSetArg(args, num_args, XmNdeleteResponse, XmDO_NOTHING); iupmotSetArg(args, num_args, XmNallowShellResize, True); /* Used so the BulletinBoard can control the shell size */ iupmotSetArg(args, num_args, XmNtitle, ""); iupmotSetArg(args, num_args, XmNvisual, iupmot_visual); if (iupmotColorMap()) iupmotSetArg(args, num_args, XmNcolormap, iupmotColorMap()); if (mwm_decor != 0x7E) iupmotSetArg(args, num_args, XmNmwmDecorations, mwm_decor); if (iupAttribGetBoolean(ih, "SAVEUNDER")) iupmotSetArg(args, num_args, XmNsaveUnder, True); parent = iupDialogGetNativeParent(ih); if (parent) ih->handle = XtCreatePopupShell(NULL, topLevelShellWidgetClass, (Widget)parent, args, num_args); else ih->handle = XtAppCreateShell(NULL, "dialog", topLevelShellWidgetClass, iupmot_display, args, num_args); if (!ih->handle) return IUP_ERROR; XmAddWMProtocolCallback(ih->handle, iupmot_wm_deletewindow, motDialogCBclose, (XtPointer)ih); XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih); XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih); XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih); XtAddEventHandler(ih->handle, StructureNotifyMask, False, (XtEventHandler)motDialogCBStructureNotifyEvent, (XtPointer)ih); XtAddCallback(ih->handle, XmNdestroyCallback, (XtCallbackProc)motDialogDestroyCallback, (XtPointer)ih); /*****************************/ /* Create the dialog manager */ /*****************************/ dialog_manager = XtVaCreateManagedWidget( "dialog_manager", xmBulletinBoardWidgetClass, ih->handle, XmNmarginWidth, 0, XmNmarginHeight, 0, XmNwidth, 100, /* set this to avoid size calculation problems */ XmNheight, 100, XmNborderWidth, 0, XmNshadowThickness, 0, XmNnoResize, iupAttribGetBoolean(ih, "RESIZE")? False: True, XmNresizePolicy, XmRESIZE_NONE, /* no automatic resize of children */ XmNuserData, ih, /* used only in motDialogConfigureNotify */ XmNnavigationType, XmTAB_GROUP, NULL); XtOverrideTranslations(dialog_manager, XtParseTranslationTable(": iupDialogConfigure()")); XtAddCallback(dialog_manager, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih); XtAddEventHandler(dialog_manager, KeyPressMask, False,(XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih); /* initialize the widget */ XtRealizeWidget(ih->handle); /* child dialogs must be always on top of the parent */ if (parent) XSetTransientForHint(iupmot_display, XtWindow(ih->handle), XtWindow(parent)); if (mwm_decor != 0x7E) /* some decoration was changed */ motDialogSetWindowManagerStyle(ih); /* Ignore VISIBLE before mapping */ iupAttribSetStr(ih, "VISIBLE", NULL); if (IupGetGlobal("_IUP_RESET_DLGBGCOLOR")) { iupmotSetGlobalColorAttrib(dialog_manager, XmNbackground, "DLGBGCOLOR"); iupmotSetGlobalColorAttrib(dialog_manager, XmNforeground, "DLGFGCOLOR"); IupSetGlobal("_IUP_RESET_DLGBGCOLOR", NULL); } return IUP_NOERROR; } static void motDialogUnMapMethod(Ihandle* ih) { Widget dialog_manager; if (ih->data->menu) { ih->data->menu->handle = NULL; /* the dialog will destroy the native menu */ IupDestroy(ih->data->menu); } dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager"); XtVaSetValues(dialog_manager, XmNuserData, NULL, NULL); XtRemoveEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih); XtRemoveEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih); XtRemoveEventHandler(ih->handle, StructureNotifyMask, False, (XtEventHandler)motDialogCBStructureNotifyEvent, (XtPointer)ih); XtRemoveCallback(ih->handle, XmNdestroyCallback, (XtCallbackProc)motDialogDestroyCallback, (XtPointer)ih); XtRemoveEventHandler(dialog_manager, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih); XtRemoveCallback(dialog_manager, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih); iupdrvBaseUnMapMethod(ih); } static void motDialogLayoutUpdateMethod(Ihandle *ih) { int border, caption, menu; if (ih->data->ignore_resize || iupAttribGet(ih, "_IUPMOT_FS_STYLE")) return; /* for dialogs the position is not updated here */ ih->data->ignore_resize = 1; iupdrvDialogGetDecoration(ih, &border, &caption, &menu); if (!iupAttribGetBoolean(ih, "RESIZE")) { int width = ih->currentwidth - 2*border; int height = ih->currentheight - 2*border - caption; XtVaSetValues(ih->handle, XmNwidth, width, XmNheight, height, XmNminWidth, width, XmNminHeight, height, XmNmaxWidth, width, XmNmaxHeight, height, NULL); } else { XtVaSetValues(ih->handle, XmNwidth, (XtArgVal)(ih->currentwidth - 2*border), /* excluding the border */ XmNheight, (XtArgVal)(ih->currentheight - 2*border - caption), NULL); } ih->data->ignore_resize = 0; } /***************************************************************/ void iupdrvDialogInitClass(Iclass* ic) { /* Driver Dependent Class methods */ ic->Map = motDialogMapMethod; ic->UnMap = motDialogUnMapMethod; ic->LayoutUpdate = motDialogLayoutUpdateMethod; ic->SetChildrenPosition = motDialogSetChildrenPositionMethod; ic->GetInnerNativeContainerHandle = motDialogGetInnerNativeContainerHandleMethod; if (!iupmot_wm_deletewindow) { /* Set up a translation table that captures "Resize" events (also called ConfigureNotify or Configure events). */ XtActionsRec rec = {"iupDialogConfigure", motDialogConfigureNotify}; XtAppAddActions(iupmot_appcontext, &rec, 1); /* register atom to intercept the close button in the window frame */ iupmot_wm_deletewindow = XmInternAtom(iupmot_display, "WM_DELETE_WINDOW", False); } /* Driver Dependent Attribute functions */ /* Visual */ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motDialogSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT); /* Overwrite Visual */ iupClassRegisterAttribute(ic, "X", motDialogGetXAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "Y", motDialogGetYAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT); /* Base Container */ iupClassRegisterAttribute(ic, "CLIENTSIZE", motDialogGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT); /* Special */ iupClassRegisterAttribute(ic, "TITLE", motDialogGetTitleAttrib, motDialogSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); /* IupDialog only */ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motDialogSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT); iupClassRegisterAttribute(ic, "ICON", NULL, motDialogSetIconAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "FULLSCREEN", NULL, motDialogSetFullScreenAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "MINSIZE", NULL, motDialogSetMinSizeAttrib, IUPAF_SAMEASSYSTEM, "1x1", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "MAXSIZE", NULL, motDialogSetMaxSizeAttrib, IUPAF_SAMEASSYSTEM, "65535x65535", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SAVEUNDER", NULL, NULL, "YES", NULL, IUPAF_NO_INHERIT); /* IupDialog X Only */ iupClassRegisterAttribute(ic, "XWINDOW", iupmotGetXWindowAttrib, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING); }