diff options
Diffstat (limited to 'iup/src/mot/iupmot_dialog.c')
-rwxr-xr-x | iup/src/mot/iupmot_dialog.c | 1069 |
1 files changed, 1069 insertions, 0 deletions
diff --git a/iup/src/mot/iupmot_dialog.c b/iup/src/mot/iupmot_dialog.c new file mode 100755 index 0000000..4eeb834 --- /dev/null +++ b/iup/src/mot/iupmot_dialog.c @@ -0,0 +1,1069 @@ +/** \file + * \brief IupDialog class + * + * See Copyright Notice in "iup.h" + */ + +#include <Xm/Xm.h> +#include <Xm/BulletinB.h> +#include <Xm/MwmUtil.h> +#include <Xm/AtomMgr.h> +#include <Xm/Protocols.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> +#include <stdarg.h> +#include <limits.h> + +#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("<Configure>: 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); +} |