A Place Where No Dreams Come True...

Current Project: A very simple X11 Dialog-Box implementation with no external dependencies.

What Does This Code Do...

Implements X11 Modal popup Dialog-Box class window. Basically... A sub-parent window of a main application window which controls it essentially making the parent window a kind of Window-Manager responsible for it's behavior. Kind of. Practically it is treated as a container window managing user input and output functionality for it's parent.

What Doesn't This Code Do...

Plenty! It is very primitive.

//-----------------------------------------------------------------------------
// dialog.c
//
//  X11 dialog box implementation.
//
// Copyright (c) 2013 - No Fun Farms A.K.A. www.smegware.com
//
//  All Smegware software is free; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This software is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//-----------------------------------------------------------------------------
//
// History...
//
//   $Source$
//   $Author$
// $Revision$
//
// $Log$
//
//-----------------------------------------------------------------------------

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>
#include <X11/xpm.h>

#include <report.h>

#include "dialog.h"
#include "xwinatom.h"
#include "xwinhlpr.h"

#define defdlgSizeBorder 2
#define defdlgItemBorder 1
#define defdlgBorder 0x00000000
#define defdlgFace 0xFFB0B080
#define defdlgAlert 0xFFC0C000
#define defdlgHilite 0xFFE0E0E0
#define defdlgShadow 0xFF505050
#define defdlgText 0x00000000
#define defdlgTextHilite 0xFF909090
#define defdlgTextShadow 0xFF505050
#define defdlgBackground 0x00000000
#define defdlgIconSize 16

struct _dialog {
  Display      *display;
  Window        parent;
  Window        window;
  GC            gc;
  Pixmap        bgnd;
  Font          font;
  XRectangle    map;
  Atom          message;
  XTextProperty xtp;
  Pixmap        icon;
  Pixmap        mask;
  unsigned      clrBorder;
  unsigned      clrFace;
  unsigned      clrAlert;
  unsigned      clrHilite;
  unsigned      clrShadow;
  unsigned      clrText;
  unsigned      clrTextHilite;
  unsigned      clrTextShadow;
  unsigned      clrBackground;
  int           bdialog;
  int           dlgborder;
  int           iconsize;
};

//-----------------------------------------------------------------------------
/*
static void dialog_set_gc_mask(pDialog dlg, Pixmap mask, int x , int y)
{
  XGCValues vals;
  vals.clip_x_origin = x;
  vals.clip_y_origin = y;
  vals.clip_mask = mask;
  XChangeGC(dlg->display, dlg->gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &vals);
}
*/
//-----------------------------------------------------------------------------

Window dialog_get_window(pDialog dlg)
{
  Window rtn = 0;
  if(dlg)
  {
    rtn = dlg->window;
  }
  return rtn;
}

//-----------------------------------------------------------------------------

GC dialog_get_gc(pDialog dlg)
{
  GC rtn = 0;
  if(dlg)
  {
    rtn = dlg->gc;
  }
  return rtn;
}

//-----------------------------------------------------------------------------

int dialog_get_width(pDialog dlg)
{
  int rtn = 0;
  if(dlg)
  {
    rtn = dlg->map.width;
  }
  return rtn;
}

//-----------------------------------------------------------------------------

int dialog_get_height(pDialog dlg)
{
  int rtn = 0;
  if(dlg)
  {
    rtn = dlg->map.height;
  }
  return rtn;
}

//-----------------------------------------------------------------------------

void dialog_draw(pDialog dlg)
{

  if(dlg)
  {
    // Start with blank canvas.
    XSetForeground(dlg->display, dlg->gc, dlg->clrFace);
    XFillRectangle(dlg->display, dlg->window, dlg->gc,
		   0,
		   0,
		   dlg->map.width,
		   dlg->map.height);
  }
}

//-----------------------------------------------------------------------------
// Increase reference count.

int dialog_enable_dialog(pDialog dlg)
{
  int ref = -1;
  if(dlg)
  {
    ref = dlg->bdialog;
    dlg->bdialog += 1;
    report(dbglevl_debug, "dialog_enable_dialog(%i).\n", dlg->bdialog);
  }
  return ref;
}

//-----------------------------------------------------------------------------
// Decrease reference count.

int dialog_disable_dialog(pDialog dlg)
{
  int ref = -1;
  if(dlg)
  {
    ref = dlg->bdialog;
    // FIXME: should catch -1 but not yet.
    dlg->bdialog -= 1;
    report(dbglevl_debug, "dilaog_disable_dilaog(%i).\n", dlg->bdialog);
  }
  return ref;
}

//-----------------------------------------------------------------------------

void dialog_size(pDialog dlg, int width, int height)
{
  if(dlg)
  {
    report(dbglevl_debug, " dialog resize w=%i h=%i.\n", width, height);
    dlg->map.width = width;
    dlg->map.height = height;
    XResizeWindow(dlg->display, dlg->window, width, height);
  }
}

//-----------------------------------------------------------------------------

void dialog_show(pDialog dlg, XEvent *event, char *title, void *icon)
{
  XWMHints hints;

  if(dlg)
  {
    report(dbglevl_debug, " dialog show w=%i h=%i.\n", dlg->map.width, dlg->map.height);
    //XMoveResizeWindow(dlg->display, dlg->window,
    //		      event.xbutton.x, event.xbutton.y, dlg->map.width, dlg->map.height);
    hints.flags = IconPixmapHint | IconMaskHint;
    if(icon)
    {
      XpmCreatePixmapFromData(dlg->display, dlg->window, icon, &hints.icon_pixmap, &hints.icon_mask, NULL);
    }
    XSetWMHints(dlg->display, dlg->window, &hints);
    dlg->xtp.value    = (unsigned char*)title;
    dlg->xtp.nitems   = strlen(title);
    XSetWMName(dlg->display, dlg->window, &dlg->xtp);
    XMapWindow(dlg->display, dlg->window);
  }
}

//-----------------------------------------------------------------------------

void dialog_hide(pDialog dlg)
{
  if(dlg)
  {
    XUnmapWindow(dlg->display, dlg->window);
    if(dlg->icon)
    {
      XFreePixmap(dlg->display, dlg->icon);
      dlg->icon = 0;
    }
    if(dlg->mask)
    {
      XFreePixmap(dlg->display, dlg->mask);
      dlg->mask = 0;
    }
    report(dbglevl_debug, " dialog hide.\n");
  }
}

//-----------------------------------------------------------------------------

void dialog_init_dialog(pDialog dlg, void *desc)
{
  if(dlg)
  {
  }
}

//-----------------------------------------------------------------------------

void dialog_destroy(pDialog *dialog)
{
  if(dialog)
  {
    pDialog dlg = *dialog;
    if(dlg)
    {
      report(dbglevl_debug, " Destroying dialog : %08X window=%08X.\n", dlg, dlg->window);
      XFreeGC(dlg->display, dlg->gc);
      free(dlg);
    }
    *dialog = NULL;
  }
}

//-----------------------------------------------------------------------------

pDialog dialog_create(Display *display, Window parent, int width, int height, Atom message)
{
  Atom atoms[2];
  XSizeHints hints;

  pDialog dlg = malloc(sizeof(Dialog));
  if(dlg)
  {
    memset(dlg, 0, sizeof(Dialog));
    dlg->display        = display;
    dlg->parent         = parent;
    dlg->map.x          = 0;
    dlg->map.y          = 0;
    dlg->map.width      = width;
    dlg->map.height     = height;
    dlg->clrBorder      = defdlgBorder;
    dlg->clrFace        = defdlgFace;
    dlg->clrAlert       = defdlgAlert;
    dlg->clrHilite      = defdlgHilite;
    dlg->clrShadow      = defdlgShadow;
    dlg->clrText        = defdlgText;
    dlg->clrTextHilite  = defdlgTextHilite;
    dlg->clrTextShadow  = defdlgTextShadow;
    dlg->clrBackground  = defdlgBackground;
    dlg->message        = message;
    dlg->window  = XCreateSimpleWindow(display,
				       DefaultRootWindow(display), // parent,
				       dlg->map.x,
				       dlg->map.y,
				       dlg->map.width,
				       dlg->map.height,
				       0,
				       WhitePixel(display, 0),
				       dlg->clrFace);
    XSelectInput(dlg->display, dlg->window, ExposureMask);
    dlg->gc = XCreateGC(dlg->display, dlg->window, 0, NULL);
    XSetTransientForHint(dlg->display, dlg->window, parent);
    hints.flags = PMinSize | PMaxSize;
    hints.min_width = hints.max_width = width;
    hints.min_height = hints.max_height = height;
    XSetWMNormalHints(dlg->display, dlg->window, &hints);
    dlg->xtp.encoding = XInternAtom(dlg->display, "STRING", False);
    dlg->xtp.format   = 8;
    xwin_set_window_property_atoms(dlg->display, dlg->window, _NET_WM_WINDOW_TYPE,
				   (unsigned char*)&_NET_WM_WINDOW_TYPE_DIALOG, 1);
    xwin_set_window_property_atoms(dlg->display, dlg->window, _NET_WM_STATE,
				   (unsigned char*)&_NET_WM_STATE_MODAL, 1);
    atoms[0] = _NET_WM_ACTION_MOVE;
    atoms[1] = _NET_WM_ACTION_CLOSE;
    xwin_set_window_property_atoms(dlg->display, dlg->window, _NET_WM_ALLOWED_ACTIONS,
				   (unsigned char*)atoms, 2);
    atoms[0] = WM_DELETE_WINDOW;
    XSetWMProtocols(dlg->display, dlg->window, atoms, 1);
    report(dbglevl_debug, " Created dialog : %08X window=%08X.\n", dlg, dlg->window);
  }
  return dlg;
}

//-----------------------------------------------------------------------------
// end: dialog.c
//

  

And The Companion Header...

//-----------------------------------------------------------------------------
// dialog.h
//
//  X11 dialog-box definition.
//
// Copyright (c) 2013 - No Fun Farms A.K.A. www.smegware.com
//
//  All Smegware software is free; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This software is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//-----------------------------------------------------------------------------
//
// History...
//
//   $Source$
//   $Author$
// $Revision$
//
// $Log$
//
//-----------------------------------------------------------------------------

typedef struct _dialog Dialog, *pDialog;

//-----------------------------------------------------------------------------

extern Window dialog_get_window(pDialog);
extern GC dialog_get_gc(pDialog);
extern int dialog_get_width(pDialog);
extern int dialog_get_height(pDialog);
extern void dialog_draw(pDialog);
extern int dialog_enable_dialog(pDialog);
extern int dialog_disable_dialog(pDialog);
extern void dialog_size(pDialog, int, int);
extern void dialog_show(pDialog, XEvent*, char*, void*);
extern void dialog_hide(pDialog);
extern void dialog_init_dialog(pDialog, void *);
extern void dialog_destroy(pDialog*);
extern pDialog dialog_create(Display*, Window, int, int, Atom);

//-----------------------------------------------------------------------------
// end: dialog.h
//

  

The Code Demonstrates The Following Programming Techniques...

Conclusion...

It is known that this code has many 'Freshman' mistakes in it. It is not claimed to be good code. Hopefully though; it demonstrates some of the less obvious interface mechanisms when communicating with both a Window-Manager and a Client program. A definition of how to use the code is also missing. Not purposely, an interface spec just can't be fit into my schedule. For now. Besides... This code is not really meant to be used. Although I use this code it is presented here purely for educational purposes.

6992