~ubuntu-branches/ubuntu/quantal/openmotif/quantal

« back to all changes in this revision

Viewing changes to demos/programs/panner/panner.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bauer
  • Date: 2010-06-23 12:12:31 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100623121231-u89gxdp51sg9wjj2
Tags: 2.3.0-1
* New Maintainer (Closes: #379258) 
* Acknowledge NMU changes
* New upstream release (Closes: #494375)
* Get rid of security patches as they are already part of new upstream
  release (00-xpmvuln.openmotif.patch, 342092-CVE-2005-3964.patch)
* Bump Standards to 3.8.4
* Added {misc:Depends} to make the package lintian cleaner
* Fix weak-library-dev-dependency by adding ${binary:Version}) for the
  -dev Package of openmotif
* Let package depend on autotools-dev to use newer autotools-helper-files
* Work around an autoconf-bug (Gentoo-Bug #1475)
* Added Client-side anti-aliased fonts support via XFT
* Added UTF-8 and UTF8_STRING atom support
* Ability to show text and pixmaps in Label, LabelGadget and all
  derived widgets
* Support of PNG/JPEG image formats in the same way as XPM is supported
* Increase FILE_OFFSET_BITS to 64 to show files >2GB in file-selector
  Idea taken from Magne Oestlyngen (Closes: #288537)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $TOG: panner.c /main/6 1997/03/31 13:38:32 dbl $ */
 
2
/*
 
3
 * @OPENGROUP_COPYRIGHT@
 
4
 * COPYRIGHT NOTICE
 
5
 * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 
6
 * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 
7
 * ALL RIGHTS RESERVED (MOTIF).  See the file named COPYRIGHT.MOTIF for
 
8
 * the full copyright text.
 
9
 * 
 
10
 * This software is subject to an open license. It may only be
 
11
 * used on, with or for operating systems which are themselves open
 
12
 * source systems. You must contact The Open Group for a license
 
13
 * allowing distribution and sublicensing of this software on, with,
 
14
 * or for operating systems which are not Open Source programs.
 
15
 * 
 
16
 * See http://www.opengroup.org/openmotif/license for full
 
17
 * details of the license agreement. Any use, reproduction, or
 
18
 * distribution of the program constitutes recipient's acceptance of
 
19
 * this agreement.
 
20
 * 
 
21
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 
22
 * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
23
 * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 
24
 * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 
25
 * OR FITNESS FOR A PARTICULAR PURPOSE
 
26
 * 
 
27
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 
28
 * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 
29
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
30
 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 
31
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
33
 * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 
34
 * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 
35
 * POSSIBILITY OF SUCH DAMAGES.
 
36
 * 
 
37
 */
 
38
/*
 
39
 * HISTORY
 
40
 */
 
41
#include <stdio.h>
 
42
#include <stdlib.h>
 
43
#include <X11/Xmd.h>
 
44
#include <Xm/TransferP.h>
 
45
#include <Xm/AtomMgr.h>
 
46
#include <Xm/CascadeB.h>
 
47
#include <Xm/DrawingA.h>
 
48
#include <Xm/Frame.h>
 
49
#include <Xm/MainW.h>
 
50
#include <Xm/MessageB.h>
 
51
#include <Xm/Notebook.h>
 
52
#include <Xm/PushB.h>
 
53
#include <Xm/RowColumn.h>
 
54
#include <Xm/SelectioB.h>
 
55
#include <Xm/XmStrDefs.h>
 
56
 
 
57
#define INIT_SCREEN_WIDTH       50
 
58
#define MAX_DISPLAY_COUNT       10
 
59
#define LOCAL                   0
 
60
#define PAN_FORMAT              8
 
61
#define PAN_SIZE                9
 
62
#define WM_SELECTION_FORMAT     "WM_S%1d"
 
63
#define COLOR_COUNT             20
 
64
 
 
65
 
 
66
String fallback[] = {
 
67
  "Panner.mappedWhenManaged:            FALSE",
 
68
  "Panner.width:                        325",
 
69
  "Panner.height:                       290",
 
70
 
 
71
  "Panner*frame.marginWidth:            7",
 
72
  "Panner*frame.marginHeight:           7",
 
73
  "Panner*notebook.firstPageNumber:     0",
 
74
 
 
75
  "Panner*tab.shadowThickness:          1",
 
76
 
 
77
  "Panner*canvas.background:            grey40",
 
78
  "Panner*canvas.foreground:            yellow",
 
79
 
 
80
 
 
81
  /* Menu entry definitions */
 
82
  "Panner*cascade1.labelString:         File",
 
83
  "Panner*cascade2.labelString:         Display",
 
84
  "Panner*cascade3.labelString:         Help",
 
85
 
 
86
  "Panner*b1.labelString:               Quit",
 
87
  "Panner*b2.labelString:               Update",
 
88
  "Panner*b3.labelString:               New Display...",
 
89
 
 
90
  "Panner*promptDlog*selectionLabelString: Display name:",
 
91
 
 
92
  "Panner*messageDlog*messageString:\
 
93
Panner Demo\\n-----------\\nGrab and move dashed box to pan display.\\n\
 
94
Use 'New Display...' command to add another display.\\n\
 
95
Select displays from tabs in the notebook.",
 
96
 
 
97
  "Panner*warningDlog*messageString:\
 
98
The panner window is not pinned!\\n\
 
99
Add the line:\\n\\n    \"Mwm*Panner*ClientPinned: True\"\\n\\n\
 
100
to your .Xdefaults file and restart Mwm.",
 
101
 
 
102
  NULL
 
103
  };
 
104
 
 
105
typedef struct _PannerInfoRec {
 
106
  Display      *display;
 
107
  Screen       *screen;
 
108
  Widget        shell;
 
109
  Widget        utmShell;       /* drawing area used for UTM */
 
110
  Widget        canvas;
 
111
  int           thumbX, thumbY;
 
112
  unsigned int  thumbW, thumbH;
 
113
  int           lastEventX, lastEventY;
 
114
  Atom          WM;             /* need selections on the correct display */
 
115
  Atom          WM_PAN;
 
116
  Atom          WM_GOTO;
 
117
  Atom          WM_PAN_POS;
 
118
} PannerInfoRec;
 
119
 
 
120
typedef struct _PanPostion {
 
121
  long x;
 
122
  long y;
 
123
} PanPosition;
 
124
 
 
125
 
 
126
typedef enum { MENU_QUIT, MENU_UPDATE, MENU_NEW, MENU_HELP } MenuFunction;
 
127
typedef enum { UNKNOWN, VERIFYING, VERIFIED } PinState;
 
128
 
 
129
/*
 
130
 * globals.
 
131
 */
 
132
XtAppContext   app;
 
133
unsigned short DSP;             /* index of active display */
 
134
Widget         notebook;
 
135
GC             thumbGC, canvasGC;
 
136
XContext       context;
 
137
PannerInfoRec *pInfoList;
 
138
unsigned long  cells[COLOR_COUNT];
 
139
PinState       pinnedState = UNKNOWN;
 
140
int            origX, origY;
 
141
 
 
142
#ifdef X_ONLY
 
143
Boolean        LOCK = False;
 
144
#endif
 
145
 
 
146
 
 
147
 
 
148
 
 
149
static void      OpenNewDisplay(String, Widget, PannerInfoRec *);
 
150
static void      UpdatePannerCB (Widget, XtPointer, XtPointer);
 
151
static void      ChangePageCB (Widget, XtPointer, XtPointer);
 
152
static void      DoAddDisplayCB (Widget, XtPointer, XtPointer);
 
153
static void      DestinationCB (Widget, XtPointer, XtPointer);
 
154
static void      DoneMoveScreenCB (Widget, XtPointer, XtPointer);
 
155
static void      WatchForWindowPanning (Display *dsp);
 
156
static void      HandlePropertyChange (XEvent *event);
 
157
static void      UpdatePannerView (PannerInfoRec *pInfoList, int remoteDsp);
 
158
static void      DrawWindows (PannerInfoRec *);
 
159
static void      DrawThumb (PannerInfoRec *);
 
160
static void      SetupColorsAndGCs();
 
161
static GC        GetXorGC (Widget);
 
162
static GC        GetCanvasGC (Widget);
 
163
static void      SetWindowColor (PannerInfoRec *, int);
 
164
static void      TranslateCoordinates (PannerInfoRec *,
 
165
                                       int, int, unsigned int, unsigned int,
 
166
                                       int*,int*,unsigned int*,unsigned int*);
 
167
static int       IgnoreError (Display *dsp, XErrorEvent *event);
 
168
static void      StartTracking (Widget, XtPointer, XEvent *, Boolean *);
 
169
static void      DoTracking (Widget, XtPointer, XEvent *, Boolean *);
 
170
static void      StopTracking (Widget, XtPointer, XEvent *, Boolean *);
 
171
static void      MoveScreen (PannerInfoRec *, int, int, Time);
 
172
static XtPointer PackCARD32 (XtPointer, CARD32);
 
173
static XtPointer PackCARD16 (XtPointer, CARD16);
 
174
static XtPointer PackCARD8 (XtPointer, CARD8);
 
175
static void      CreateMenuBar (Widget parent);
 
176
static void      MenuCB (Widget w, XtPointer clientData, XtPointer callData);
 
177
static void      DoUpdatePanner ();
 
178
static void      DoAddDisplay ();
 
179
static void      DoHelp ();
 
180
static void      DoQuit ();
 
181
static void      CheckPinnedState ();
 
182
static void      ShowPinStateWarning ();
 
183
static void      HandleInitialExpose (Widget, XtPointer, XEvent *, Boolean *);
 
184
 
 
185
 
 
186
 
 
187
 
 
188
/*----------------------------------------------------------------*
 
189
 |                             main                               |
 
190
 *----------------------------------------------------------------*/
 
191
int
 
192
main (int argc, char** argv)
 
193
{
 
194
  Widget mainWin, frame;
 
195
  XEvent event;
 
196
  
 
197
 
 
198
  pInfoList = (PannerInfoRec *) XtMalloc(sizeof(PannerInfoRec) *
 
199
                                         MAX_DISPLAY_COUNT);
 
200
  for (DSP = 0;  DSP < MAX_DISPLAY_COUNT;  DSP++)
 
201
    pInfoList[DSP].display = NULL;
 
202
  DSP = LOCAL;
 
203
    
 
204
  XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); 
 
205
    
 
206
 
 
207
  pInfoList[LOCAL].shell   = XtVaOpenApplication(&app, "Panner", NULL, 0,
 
208
                                               &argc, argv, 
 
209
                                               fallback,
 
210
                                               sessionShellWidgetClass, NULL);
 
211
  pInfoList[LOCAL].display = XtDisplay(pInfoList[LOCAL].shell);
 
212
 
 
213
 
 
214
  mainWin = XmCreateMainWindow(pInfoList[LOCAL].shell, "mainWin", NULL, 0);
 
215
  XtManageChild(mainWin);
 
216
  CreateMenuBar(mainWin);
 
217
 
 
218
  frame     = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, mainWin,
 
219
                                      NULL);
 
220
  notebook  = XtVaCreateManagedWidget("notebook", xmNotebookWidgetClass, frame,
 
221
                                      NULL);
 
222
 
 
223
  XtRealizeWidget(pInfoList[LOCAL].shell);
 
224
 
 
225
  context  = XUniqueContext ();
 
226
  OpenNewDisplay(/*$DISPLAY*/NULL, notebook, pInfoList);
 
227
 
 
228
  SetupColorsAndGCs();
 
229
 
 
230
  XtAddCallback(notebook, XmNpageChangedCallback, ChangePageCB, pInfoList);
 
231
  XtAddEventHandler(notebook, ExposureMask, False, HandleInitialExpose, NULL);
 
232
 
 
233
  XtMapWidget(pInfoList[LOCAL].shell);
 
234
  
 
235
  for (;;)
 
236
    {
 
237
      XtAppNextEvent(app, &event);
 
238
 
 
239
      if (event.type == PropertyNotify)
 
240
        HandlePropertyChange(&event);
 
241
 
 
242
      XtDispatchEvent(&event);
 
243
 
 
244
    }
 
245
}
 
246
 
 
247
 
 
248
 
 
249
 
 
250
/*----------------------------------------------------------------*
 
251
 |                        OpenNewDisplay                          |
 
252
 | - Get new display connection to named display.                 |
 
253
 | - If display name is not NULL, create shell on the display.    |
 
254
 | - Fill in correct record in pInfoList.                         |
 
255
 *----------------------------------------------------------------*/
 
256
static void
 
257
OpenNewDisplay(
 
258
     String         displayName,
 
259
     Widget         notebook,
 
260
     PannerInfoRec *pInfoList)
 
261
{
 
262
  int             newDsp = 0;
 
263
  int             argc = 0;
 
264
  char          **argv = NULL;
 
265
  Dimension       canvasW, canvasH;
 
266
  char            selectionName[40];
 
267
  PannerInfoRec  *pInfo;
 
268
  Widget          tab;
 
269
  XmString        tabName;
 
270
  XtCallbackList  cbList;
 
271
 
 
272
 
 
273
  /*
 
274
   * If NULL, then the display's already been created.
 
275
   */
 
276
  if (displayName != NULL)
 
277
    {
 
278
      XtVaGetValues(notebook, XmNlastPageNumber, &newDsp,
 
279
                    XmNpageChangedCallback, &cbList, NULL);
 
280
      newDsp++;
 
281
 
 
282
 
 
283
      if ((pInfoList[newDsp].display = XOpenDisplay(displayName)) == NULL)
 
284
        {
 
285
          fprintf(stderr, "ERROR - Can't open display \"%s\".\n", displayName);
 
286
          return;
 
287
        }
 
288
 
 
289
      XtDisplayInitialize(app, pInfoList[newDsp].display, "panner", "Panner",
 
290
                          NULL, 0, &argc, argv);
 
291
 
 
292
      /* create an unmapped shell on the remote display */
 
293
      pInfoList[newDsp].shell =
 
294
        XtVaAppCreateShell( "panner", "Panner", applicationShellWidgetClass,
 
295
                           pInfoList[newDsp].display,
 
296
                           XmNmappedWhenManaged, False, NULL);
 
297
 
 
298
      XtRealizeWidget(pInfoList[newDsp].shell);
 
299
    }
 
300
  /*
 
301
   * For UTM to work, there must be a drawing area or UTM saavy
 
302
   * widget.
 
303
   *
 
304
   *  We must set-up a destination callback function that
 
305
   *  does the actual transfer of the parameter info to Mwm.
 
306
   */
 
307
  
 
308
  pInfoList[newDsp].utmShell
 
309
    = XtVaCreateManagedWidget("utmShell", xmDrawingAreaWidgetClass,
 
310
                              pInfoList[newDsp].shell,
 
311
                              XmNmappedWhenManaged, False,
 
312
                              NULL);
 
313
  
 
314
  XtAddCallback(pInfoList[newDsp].utmShell, XmNdestinationCallback,
 
315
                DestinationCB, &(pInfoList[newDsp]));
 
316
 
 
317
  /*
 
318
   * Initialize the correct record in the pInfoList.
 
319
   */
 
320
  pInfoList[newDsp].screen = XtScreen(pInfoList[newDsp].shell);
 
321
 
 
322
 
 
323
  /*
 
324
   * setup handler to watch when Mwm changes the root property.
 
325
   * first store some data on the root window.
 
326
   */
 
327
  XSaveContext(pInfoList[newDsp].display,
 
328
               DefaultRootWindow(pInfoList[newDsp].display),
 
329
               context,
 
330
               (XPointer)(long)newDsp); /* store index into panner info. */
 
331
  WatchForWindowPanning(pInfoList[newDsp].display);
 
332
 
 
333
 
 
334
  /*
 
335
   * Add another page to the notebook.
 
336
   * First must set size correctly.
 
337
   */
 
338
 
 
339
  XtVaGetValues(pInfoList[LOCAL].shell,
 
340
                 XmNwidth, &canvasW, XmNheight, &canvasH, NULL);
 
341
  pInfoList[newDsp].canvas
 
342
    = XtVaCreateManagedWidget("canvas", xmDrawingAreaWidgetClass, notebook,
 
343
                              XmNchildType, XmPAGE,
 
344
                              XmNpageNumber, newDsp,
 
345
                              XmNwidth, canvasW,
 
346
                              XmNheight, canvasH,
 
347
                              NULL);
 
348
  XtAddCallback(pInfoList[newDsp].canvas, XmNexposeCallback, UpdatePannerCB,
 
349
                pInfoList);
 
350
 
 
351
  if (displayName == NULL)
 
352
    tabName = XmStringCreate("LOCAL",XmFONTLIST_DEFAULT_TAG);
 
353
  else
 
354
    tabName = XmStringCreate(displayName,XmFONTLIST_DEFAULT_TAG);
 
355
  tab = XtVaCreateManagedWidget("tab", xmPushButtonWidgetClass, notebook,
 
356
                                XmNlabelString, tabName,
 
357
                                XmNchildType, XmMAJOR_TAB, NULL);
 
358
  XmStringFree(tabName);
 
359
 
 
360
  pInfoList[newDsp].thumbW = INIT_SCREEN_WIDTH;
 
361
  pInfoList[newDsp].thumbH = pInfoList[newDsp].thumbW *
 
362
                             HeightOfScreen(pInfoList[newDsp].screen) /
 
363
                             WidthOfScreen(pInfoList[newDsp].screen);
 
364
  XtVaGetValues(pInfoList[newDsp].canvas, XmNwidth,  &canvasW,
 
365
                                          XmNheight, &canvasH, NULL);
 
366
  pInfoList[newDsp].thumbX = (int)canvasW/2 - (int)pInfoList[newDsp].thumbW/2;
 
367
  pInfoList[newDsp].thumbY = (int)canvasH/2 - (int)pInfoList[newDsp].thumbH/2;
 
368
  
 
369
  /* Setup the atoms needed to communicate with Mwm. Check screen number! */
 
370
  sprintf(selectionName, WM_SELECTION_FORMAT,
 
371
          XScreenNumberOfScreen(pInfoList[newDsp].screen));
 
372
  pInfoList[newDsp].WM         = XmInternAtom(pInfoList[newDsp].display,
 
373
                                              selectionName, False);
 
374
  pInfoList[newDsp].WM_PAN     = XmInternAtom(pInfoList[newDsp].display,
 
375
                                              "_MOTIF_WM_PAN", False);
 
376
  pInfoList[newDsp].WM_GOTO    = XmInternAtom(pInfoList[newDsp].display,
 
377
                                              "_MOTIF_WM_GOTO", False);
 
378
  pInfoList[newDsp].WM_PAN_POS = XmInternAtom(pInfoList[newDsp].display,
 
379
                                              "_MOTIF_WM_PAN_POSITION", False);
 
380
 
 
381
  XtAddEventHandler(pInfoList[newDsp].canvas, ButtonPressMask, False,
 
382
                    StartTracking, (XtPointer)&pInfoList[newDsp]);
 
383
}
 
384
 
 
385
 
 
386
 
 
387
/*========================== CALLBACKS ==========================*/
 
388
 
 
389
/*----------------------------------------------------------------*
 
390
 |                        UpdatePannerCB                          |
 
391
 *----------------------------------------------------------------*/
 
392
static void
 
393
UpdatePannerCB (
 
394
     Widget    w,
 
395
     XtPointer clientData,
 
396
     XtPointer callData)
 
397
{
 
398
  XmDrawingAreaCallbackStruct *cb = (XmDrawingAreaCallbackStruct *)callData;
 
399
  PannerInfoRec *pInfoList = (PannerInfoRec *)clientData;
 
400
 
 
401
  if (cb->reason == XmCR_EXPOSE)
 
402
    {
 
403
      XExposeEvent *event = (XExposeEvent *)cb->event;
 
404
 
 
405
      /* Last expose event received - do the drawing. */
 
406
      if (event->count == 0)
 
407
        UpdatePannerView(pInfoList, DSP);
 
408
    }
 
409
 
 
410
  else
 
411
    /*
 
412
     * Update button pressed.
 
413
     */
 
414
    UpdatePannerView(pInfoList, DSP);
 
415
}
 
416
 
 
417
 
 
418
/*----------------------------------------------------------------*
 
419
 |                         ChangePageCB                           |
 
420
 | Invoked just prior to notebook page change. Any drawing here   |
 
421
 | would be lost.                                                 |
 
422
 *----------------------------------------------------------------*/
 
423
static void
 
424
ChangePageCB (
 
425
     Widget    w,
 
426
     XtPointer clientData,
 
427
     XtPointer callData)
 
428
{
 
429
  PannerInfoRec            *pInfoList = (PannerInfoRec *)clientData;
 
430
  XmNotebookCallbackStruct *nbData    = (XmNotebookCallbackStruct *)callData;
 
431
  int  pageNumber;
 
432
 
 
433
  pageNumber = nbData->page_number;
 
434
  if ((pageNumber >= MAX_DISPLAY_COUNT) ||
 
435
      (pInfoList[pageNumber].display == NULL))
 
436
    {
 
437
      fprintf(stderr, "ERROR - bad display index. (%d).\n", pageNumber);
 
438
    }
 
439
  else
 
440
    {
 
441
      DSP = pageNumber;
 
442
    }
 
443
}
 
444
 
 
445
 
 
446
/*----------------------------------------------------------------*
 
447
 |                        DoAddDisplayCB                          |
 
448
 *----------------------------------------------------------------*/
 
449
static void
 
450
DoAddDisplayCB (
 
451
     Widget    w,
 
452
     XtPointer clientData,
 
453
     XtPointer callData)
 
454
{
 
455
  XmSelectionBoxCallbackStruct *cb = (XmSelectionBoxCallbackStruct *)callData;
 
456
  PannerInfoRec *pInfoList = (PannerInfoRec *)clientData;
 
457
  char          *dspName;           /* Free when done. */
 
458
  String         appName, appClass; /* Don't free - owned by Xt. */
 
459
 
 
460
 
 
461
  XtGetApplicationNameAndClass(pInfoList[LOCAL].display, &appName, &appClass);
 
462
  XmStringGetLtoR(cb->value, XmSTRING_DEFAULT_CHARSET, &dspName);
 
463
 
 
464
  OpenNewDisplay(dspName, notebook, pInfoList);
 
465
  if (dspName) XtFree(dspName);
 
466
}
 
467
 
 
468
 
 
469
/*----------------------------------------------------------------*
 
470
 |                         DestinationCB                          |
 
471
 | This function gets invoked by UTM when a sink has been estab-  |
 
472
 | lished and a request initiated against another selection.  The |
 
473
 | purpose here is to set-up the parameters and pass them to the  |
 
474
 | owner of the selection.  The parameter data has already been   |
 
475
 | allocated in the MoveScreen() function.                        |
 
476
 | clientData holds the pannerInfoRec corresponding to the right  |
 
477
 | display.                                                       |
 
478
 *----------------------------------------------------------------*/
 
479
static void
 
480
DestinationCB (
 
481
     Widget w,
 
482
     XtPointer clientData,
 
483
     XtPointer callData)
 
484
{
 
485
  XmDestinationCallbackStruct *dcs = (XmDestinationCallbackStruct *)callData;
 
486
  PannerInfoRec *pInfo = (PannerInfoRec *)clientData;
 
487
  Atom target;
 
488
 
 
489
 
 
490
  /*
 
491
   * Pass the data to free in the clientData field.
 
492
   * location_data points to the param data. This was set in
 
493
   * MoveScreen().
 
494
   */
 
495
 
 
496
  /* FIRST - setup the parameters to pass. */
 
497
  XmTransferSetParameters(dcs->transfer_id,
 
498
                          dcs->location_data,   /* pointer to param data. */
 
499
                          PAN_FORMAT,
 
500
                          PAN_SIZE,             /* should be calculated. */
 
501
                          dcs->selection);      /* type - don't care. */
 
502
 
 
503
  /* LAST - Make the transfer. */
 
504
  XmTransferValue(dcs->transfer_id,
 
505
                  pInfo->WM_PAN,        /* target for conversion. */
 
506
                  DoneMoveScreenCB,     /* CB proc invoked when done. */
 
507
                  dcs->location_data,   /* clientData - to be freed. */
 
508
                  dcs->time);
 
509
}
 
510
 
 
511
 
 
512
 
 
513
/*----------------------------------------------------------------*
 
514
 |                       DoneMoveScreenCB                         |
 
515
 *----------------------------------------------------------------*/
 
516
static void
 
517
DoneMoveScreenCB (
 
518
     Widget w,
 
519
     XtPointer clientData,
 
520
     XtPointer callData)
 
521
{
 
522
  /*
 
523
   * Conversion completed. Safe to free param data.
 
524
   */
 
525
 
 
526
  XtFree((char *)clientData);
 
527
}
 
528
 
 
529
 
 
530
 
 
531
 
 
532
 
 
533
 
 
534
/*=========================== PAN-HANDLING ==========================*/
 
535
 
 
536
 
 
537
/*----------------------------------------------------------------*
 
538
 |                     WatchForWindowPanning                      |
 
539
 *----------------------------------------------------------------*/
 
540
static void
 
541
WatchForWindowPanning (Display *dsp)
 
542
{
 
543
  XWindowAttributes attr;
 
544
  Window rwin     = DefaultRootWindow(dsp);
 
545
 
 
546
 
 
547
  /* Watch whenever the window manager's panning position changes. */
 
548
  /* Mwm stores the position in properties on the root window.     */
 
549
  /* This is stored in the _MOTIF_WM_PAN_POSITION property.        */
 
550
 
 
551
  XGetWindowAttributes(dsp, rwin, &attr);
 
552
 
 
553
  if (! (attr.your_event_mask & PropertyChangeMask))
 
554
    XSelectInput(dsp, rwin, attr.your_event_mask | PropertyChangeMask);
 
555
}
 
556
 
 
557
 
 
558
 
 
559
/*----------------------------------------------------------------*
 
560
 |                     HandlePropertyChange                       |
 
561
 | This routine checks the property changed and if its the right  |
 
562
 | property, grab the new panning position.                       |
 
563
 *----------------------------------------------------------------*/
 
564
static void
 
565
HandlePropertyChange (XEvent *event)
 
566
{
 
567
  XPropertyEvent *propEvent = (XPropertyEvent *)event;
 
568
  int             iDsp;
 
569
 
 
570
 
 
571
  /* Get the correct info record stored with the context manager. */
 
572
  if (XFindContext(propEvent->display, propEvent->window, context,
 
573
                   (XPointer*)&iDsp))
 
574
    return;
 
575
 
 
576
  /* check if this is the right one. Othersize, we'll update when another
 
577
   * display changes.
 
578
   */
 
579
  if (propEvent && propEvent->atom != pInfoList[iDsp].WM_PAN_POS)
 
580
    return;
 
581
 
 
582
  /* if the display doesn't match the current one, then punt. */
 
583
  if (iDsp == DSP)
 
584
    {
 
585
      if (pinnedState == VERIFIED)
 
586
        UpdatePannerView(pInfoList, iDsp);
 
587
      else
 
588
        {
 
589
          Window        rWin, child;
 
590
          int           x, y, newX, newY;
 
591
          unsigned int  width, height, bWidth, depth;
 
592
 
 
593
          /* Get position of the top-level shell */
 
594
          XGetGeometry(pInfoList[LOCAL].display, XtWindow(pInfoList[LOCAL].shell),
 
595
                       &rWin, &x, &y, &width, &height, &bWidth, &depth);
 
596
 
 
597
          XTranslateCoordinates(pInfoList[LOCAL].display,
 
598
                                XtWindow(pInfoList[LOCAL].shell),
 
599
                                rWin, x, y, &newX, &newY, &child);
 
600
  
 
601
          if ((newX == origX) && (newY == origY))
 
602
            pinnedState = VERIFIED;
 
603
          else
 
604
            ShowPinStateWarning();
 
605
        }
 
606
    }
 
607
 
 
608
#ifdef X_ONLY
 
609
  LOCK = False;
 
610
#endif
 
611
}
 
612
 
 
613
 
 
614
 
 
615
/*============================ DRAWING ===========================*/
 
616
 
 
617
/*----------------------------------------------------------------*
 
618
 |                         UpdatePannerView                       |
 
619
 *----------------------------------------------------------------*/
 
620
static void
 
621
UpdatePannerView (
 
622
     PannerInfoRec *pInfoList,
 
623
     int remoteDsp)
 
624
{
 
625
  XClearArea(pInfoList[LOCAL].display,
 
626
             XtWindow(pInfoList[remoteDsp].canvas),
 
627
             0, 0, 0, 0, False);
 
628
 
 
629
  DrawWindows(pInfoList);
 
630
  DrawThumb(&pInfoList[remoteDsp]);
 
631
}
 
632
 
 
633
 
 
634
/*----------------------------------------------------------------*
 
635
 |                          DrawWindows                           |
 
636
 *----------------------------------------------------------------*/
 
637
static void
 
638
DrawWindows (PannerInfoRec *pInfoList)
 
639
{
 
640
  Window        realRoot, root, parent, *child = NULL;
 
641
  int           i, x, y;
 
642
  unsigned int  childCount, width, height;
 
643
  int (*oldHandler)();
 
644
 
 
645
  
 
646
  realRoot = RootWindow(pInfoList[DSP].display,
 
647
                        XScreenNumberOfScreen(pInfoList[DSP].screen));
 
648
 
 
649
  if (XQueryTree(pInfoList[DSP].display, realRoot,
 
650
                 &root, &parent, &child, &childCount))
 
651
    {
 
652
      /*
 
653
       * We need to install an error handler since the window-tree may
 
654
       * become invalid while where still processing the list.
 
655
       */
 
656
      oldHandler = XSetErrorHandler(IgnoreError);
 
657
      for (i=0; i<childCount; i++)
 
658
        {
 
659
          XWindowAttributes attr;
 
660
          
 
661
          XGetWindowAttributes(pInfoList[DSP].display, child[i], &attr);
 
662
          
 
663
          if (attr.map_state == IsViewable)
 
664
            {
 
665
              TranslateCoordinates(&pInfoList[DSP],
 
666
                                   attr.x, attr.y, attr.width, attr.height,
 
667
                                   &x, &y, &width, &height);
 
668
              
 
669
              SetWindowColor (&pInfoList[LOCAL], i);
 
670
              XFillRectangle(pInfoList[LOCAL].display,
 
671
                             XtWindow(pInfoList[DSP].canvas),
 
672
                             canvasGC, x, y, width, height);
 
673
            }
 
674
        }
 
675
      XSetErrorHandler(oldHandler);
 
676
 
 
677
      if (child != NULL)
 
678
        XFree((char*)child);
 
679
    }
 
680
}
 
681
 
 
682
 
 
683
/*----------------------------------------------------------------*
 
684
 |                          DrawThumb                             |
 
685
 *----------------------------------------------------------------*/
 
686
static void
 
687
DrawThumb (PannerInfoRec *pInfo)
 
688
{
 
689
  XDrawRectangle(XtDisplay(pInfo->canvas), XtWindow(pInfo->canvas), thumbGC,
 
690
                 pInfo->thumbX, pInfo->thumbY,
 
691
                 pInfo->thumbW, pInfo->thumbH);
 
692
}
 
693
 
 
694
 
 
695
/*----------------------------------------------------------------*
 
696
 |                       SetupColorsAndGCs                        |
 
697
 | Called once at the beginning to setup some drawing stuff.      |
 
698
 *----------------------------------------------------------------*/
 
699
static void
 
700
SetupColorsAndGCs()
 
701
{
 
702
  int i;
 
703
  XColor color;
 
704
  Colormap cmap = DefaultColormapOfScreen(pInfoList[LOCAL].screen);    
 
705
 
 
706
  /*
 
707
   * set-up the global GCs.
 
708
   */
 
709
  thumbGC  = GetXorGC(pInfoList[LOCAL].canvas);
 
710
  canvasGC = GetCanvasGC(pInfoList[LOCAL].canvas);
 
711
 
 
712
  /*
 
713
   * Allocate the global color cells for the drawing of each windows.
 
714
   * The more random the colors, the better.
 
715
   */
 
716
  if (XAllocColorCells(pInfoList[LOCAL].display,
 
717
                       cmap, False, NULL, 0, cells, COLOR_COUNT))
 
718
    for (i=0; i<COLOR_COUNT; i++)
 
719
      {
 
720
        color.red = rand() % 65535;
 
721
        color.blue = rand() % 65535;
 
722
        color.green = rand() % 65535;
 
723
        color.pixel = cells[i];
 
724
        XStoreColor(pInfoList[LOCAL].display, cmap, &color);
 
725
      }
 
726
}
 
727
 
 
728
 
 
729
/*----------------------------------------------------------------*
 
730
 |                           GetXorGC                             |
 
731
 *----------------------------------------------------------------*/
 
732
static GC
 
733
GetXorGC (Widget w)
 
734
{
 
735
  GC        gc;
 
736
  XGCValues values;
 
737
 
 
738
 
 
739
  XtVaGetValues(w, XmNforeground, &values.foreground,
 
740
                XmNbackground, &values.background, NULL);
 
741
  values.foreground = values.foreground ^ values.background;
 
742
  values.function = GXxor;
 
743
  values.line_style = LineOnOffDash;
 
744
 
 
745
  gc = XtGetGC(w,
 
746
               GCForeground | GCBackground | GCFunction | GCLineStyle,
 
747
               &values);
 
748
 
 
749
  return(gc);
 
750
}
 
751
 
 
752
 
 
753
/*----------------------------------------------------------------*
 
754
 |                         GetCanvasGC                            |
 
755
 *----------------------------------------------------------------*/
 
756
static GC
 
757
GetCanvasGC (Widget w)
 
758
{
 
759
  GC        gc;
 
760
  XGCValues values;
 
761
 
 
762
 
 
763
  XtVaGetValues(w, XmNforeground, &values.foreground,
 
764
                XmNbackground, &values.background, NULL);
 
765
  values.foreground = values.background;
 
766
  values.function = GXcopy;
 
767
 
 
768
  gc = XtGetGC(w,
 
769
               GCForeground | GCBackground | GCFunction,
 
770
               &values);
 
771
 
 
772
  return(gc);
 
773
}
 
774
 
 
775
 
 
776
/*----------------------------------------------------------------*
 
777
 |                       SetWindowColor                           |
 
778
 *----------------------------------------------------------------*/
 
779
static void
 
780
SetWindowColor (PannerInfoRec *pInfo, int i)
 
781
{
 
782
  XSetForeground(pInfo->display, canvasGC, cells[(i+1)%COLOR_COUNT]);
 
783
}
 
784
 
 
785
 
 
786
/*----------------------------------------------------------------*
 
787
 |                     TranslateCoordinates                       |
 
788
 *----------------------------------------------------------------*/
 
789
static void
 
790
TranslateCoordinates (
 
791
     PannerInfoRec *pInfo,
 
792
     int  x1, int  y1, unsigned int  width1, unsigned int  height1,
 
793
     int *x2, int *y2, unsigned int *width2, unsigned int *height2)
 
794
{
 
795
  int rootW, rootH;
 
796
 
 
797
 
 
798
  rootW = WidthOfScreen(pInfo->screen);
 
799
  rootH = HeightOfScreen(pInfo->screen);
 
800
 
 
801
  *x2      = x1      * (int)pInfo->thumbW / (int)rootW + pInfo->thumbX;
 
802
  *y2      = y1      * (int)pInfo->thumbH / (int)rootH + pInfo->thumbY;
 
803
  *width2  = width1  * pInfo->thumbW / rootW;
 
804
  *height2 = height1 * pInfo->thumbH / rootH;
 
805
}
 
806
 
 
807
 
 
808
/*----------------------------------------------------------------*
 
809
 |                          IgnoreError                           |
 
810
 *----------------------------------------------------------------*/
 
811
static int 
 
812
IgnoreError (Display *dsp, XErrorEvent *event)
 
813
{
 
814
  /*
 
815
   * Do Nothing...
 
816
   * This is needed since we will may be updating the list of window
 
817
   * while one of them goes away.  Ie: the window list received from
 
818
   * XQueryTree may not be valid for the entire loop where we get each
 
819
   * window's geometry.
 
820
   */
 
821
        return 0;       /* make compiler happy */
 
822
}
 
823
 
 
824
 
 
825
 
 
826
/*======================= TRACKING HANDLERS ======================*/
 
827
 
 
828
 
 
829
/*----------------------------------------------------------------*
 
830
 |                         StartTracking                          |
 
831
 *----------------------------------------------------------------*/
 
832
static void
 
833
StartTracking (
 
834
     Widget     w,
 
835
     XtPointer  clientData,
 
836
     XEvent    *event,
 
837
     Boolean   *dispatch)
 
838
{
 
839
  PannerInfoRec      *pInfo       = (PannerInfoRec *)clientData;
 
840
  XPointerMovedEvent *motionEvent = (XPointerMovedEvent *)event;
 
841
 
 
842
 
 
843
  if ((pinnedState == VERIFIED) && (event->xbutton.button == Button1))
 
844
    {
 
845
      pInfo->lastEventX = event->xbutton.x;
 
846
      pInfo->lastEventY = event->xbutton.y;
 
847
 
 
848
      if ((event->xbutton.x < pInfo->thumbX) ||
 
849
          (event->xbutton.y < pInfo->thumbY) ||
 
850
          (event->xbutton.x > pInfo->thumbX + (int)pInfo->thumbW) || 
 
851
          (event->xbutton.y > pInfo->thumbY + (int)pInfo->thumbH))
 
852
        {
 
853
          /*
 
854
           * if on the canvas, then center the thumb over the pointer.
 
855
           */
 
856
 
 
857
          MoveScreen(pInfo,
 
858
                     event->xbutton.x - (int)pInfo->thumbW/2,
 
859
                     event->xbutton.y - (int)pInfo->thumbH/2,
 
860
                     motionEvent->time);
 
861
        }
 
862
 
 
863
      XtAddEventHandler(w, ButtonReleaseMask, False, StopTracking, clientData);
 
864
      XtAddEventHandler(w, Button1MotionMask, False, DoTracking,   clientData);
 
865
    }
 
866
  else if (pinnedState != VERIFIED)
 
867
    CheckPinnedState ();
 
868
}
 
869
 
 
870
 
 
871
/*----------------------------------------------------------------*
 
872
 |                          DoTracking                            |
 
873
 *----------------------------------------------------------------*/
 
874
static void
 
875
DoTracking (
 
876
     Widget w,
 
877
     XtPointer clientData,
 
878
     XEvent *event,
 
879
     Boolean *dispatch)
 
880
{
 
881
  PannerInfoRec      *pInfo       = (PannerInfoRec *)clientData;
 
882
  XPointerMovedEvent *motionEvent = (XPointerMovedEvent *)event;
 
883
 
 
884
 
 
885
  MoveScreen(pInfo,
 
886
             pInfo->thumbX + event->xbutton.x - pInfo->lastEventX,
 
887
             pInfo->thumbY + event->xbutton.y - pInfo->lastEventY,
 
888
             motionEvent->time);
 
889
 
 
890
  pInfo->lastEventX = event->xbutton.x;
 
891
  pInfo->lastEventY = event->xbutton.y;
 
892
}
 
893
 
 
894
 
 
895
/*----------------------------------------------------------------*
 
896
 |                         StopTracking                           |
 
897
 *----------------------------------------------------------------*/
 
898
static void
 
899
StopTracking (
 
900
     Widget     w,
 
901
     XtPointer  clientData,
 
902
     XEvent    *event,
 
903
     Boolean   *dispatch)
 
904
{
 
905
  if (event->xbutton.button == Button1)
 
906
    {
 
907
      XtRemoveEventHandler(w, Button1MotionMask, False, DoTracking,
 
908
                           clientData);
 
909
      XtRemoveEventHandler(w, ButtonReleaseMask, False, StopTracking,
 
910
                           clientData);
 
911
    }
 
912
}
 
913
 
 
914
 
 
915
 
 
916
/*----------------------------------------------------------------*
 
917
 |                          MoveScreen                            |
 
918
 *----------------------------------------------------------------*/
 
919
static void
 
920
MoveScreen (
 
921
     PannerInfoRec *pInfo,
 
922
     int            newX,
 
923
     int            newY,
 
924
     Time           time)
 
925
{
 
926
  int           dx, dy, panDx, panDy, rootW, rootH;
 
927
  XtPointer     msg, fulldata;
 
928
  unsigned long size;
 
929
 
 
930
  
 
931
  DrawThumb(pInfo);
 
932
 
 
933
  dx = newX - pInfo->thumbX;
 
934
  dy = newY - pInfo->thumbY;
 
935
 
 
936
  pInfo->thumbX = newX;
 
937
  pInfo->thumbY = newY;
 
938
 
 
939
  DrawThumb(pInfo);
 
940
 
 
941
 
 
942
  /*
 
943
   * Send Pan message to mwm.
 
944
   */
 
945
 
 
946
  rootW = WidthOfScreen(pInfo->screen);
 
947
  rootH = HeightOfScreen(pInfo->screen);
 
948
  panDx = -(dx * rootW / (int)pInfo->thumbW);
 
949
  panDy = -(dy * rootH / (int)pInfo->thumbH);
 
950
 
 
951
  size  = sizeof(CARD32);  /* panDx */
 
952
  size += sizeof(CARD32);  /* panDy */
 
953
  size += sizeof(CARD8);   /* config */
 
954
 
 
955
  msg = fulldata = (XtPointer) XtMalloc(sizeof(CARD8) * size);
 
956
 
 
957
  msg = PackCARD32(msg, panDx);
 
958
  msg = PackCARD32(msg, panDy);
 
959
  msg = PackCARD8(msg, True);
 
960
 
 
961
#ifdef X_ONLY
 
962
  {
 
963
    Display       *display;
 
964
    Window         window;
 
965
    Atom           MY_PANNER_PROP;
 
966
 
 
967
 
 
968
    display = XtDisplay(notebook); /* notebook just happens to be a global. */
 
969
    window = XtWindow(notebook);
 
970
    
 
971
    MY_PANNER_PROP = XInternAtom(display, "MY_PANNER_PROP", False);
 
972
 
 
973
 
 
974
    /*
 
975
     * Note - to really make this work across multiple displays,
 
976
     * the window argument must reside on the same display as WM_Si.
 
977
     */
 
978
 
 
979
    /*
 
980
     * Use a lock to make sure the property was read by Mwm.
 
981
     * When the pan-property is updated, it's safe to make another
 
982
     * conversion.
 
983
     */
 
984
    if (!LOCK)
 
985
      {
 
986
        LOCK = True; /* Freed in HandlePropertyChange. */
 
987
        XChangeProperty(display, window, MY_PANNER_PROP, MY_PANNER_PROP,
 
988
                        PAN_FORMAT, PropModeReplace,
 
989
                        (unsigned char *)fulldata, size);
 
990
 
 
991
        XConvertSelection(pInfo->display, pInfo->WM, pInfo->WM_PAN,
 
992
                          MY_PANNER_PROP,
 
993
                          window, time);
 
994
      }
 
995
  }
 
996
#else
 
997
  if (! XmeNamedSink(pInfo->utmShell,   /* widget with destination callback */
 
998
                     pInfo->WM, /* named selection - ie. Window Manager */
 
999
                     XmCOPY,            /* operation to perform on the data */
 
1000
                     (XtPointer)fulldata, /* pointer to param data, */
 
1001
                     time)                /*  free n TransferDone proc. */
 
1002
      )
 
1003
    printf("Error - UTM Transfer failed.\n");
 
1004
#endif /* X_ONLY */
 
1005
}
 
1006
 
 
1007
 
 
1008
 
 
1009
/*----------------------------------------------------------------*
 
1010
 |                      PACKING FUNCTIONS                         |
 
1011
 *----------------------------------------------------------------*/
 
1012
 
 
1013
static XtPointer
 
1014
PackCARD32 (XtPointer data, CARD32 val)
 
1015
{
 
1016
  CARD16 bottom = val & (0xFFFF);
 
1017
  CARD16 top = val >> 16;
 
1018
 
 
1019
  data = PackCARD16(data, top);
 
1020
  data = PackCARD16(data, bottom);
 
1021
  return(data);
 
1022
}
 
1023
 
 
1024
 
 
1025
static XtPointer
 
1026
PackCARD16 (XtPointer data, CARD16 val)
 
1027
{
 
1028
  CARD8 bottom = val & (0xFF);
 
1029
  CARD8 top = val >> 8;
 
1030
 
 
1031
  data = PackCARD8(data, top);
 
1032
  data = PackCARD8(data, bottom);
 
1033
  return(data);
 
1034
}
 
1035
 
 
1036
 
 
1037
static XtPointer
 
1038
PackCARD8 (XtPointer data, CARD8 val)
 
1039
{
 
1040
  CARD8 *ptr = (CARD8 *) data;
 
1041
 
 
1042
  *ptr = (CARD8) val;
 
1043
  data = ((char*)data) + 1;
 
1044
  return(data);
 
1045
}
 
1046
 
 
1047
 
 
1048
/*======================= USER INTERFACE ======================*/
 
1049
 
 
1050
/*----------------------------------------------------------------*
 
1051
 |                         CreateMenuBar                          |
 
1052
 *----------------------------------------------------------------*/
 
1053
static void
 
1054
CreateMenuBar (Widget parent)
 
1055
{
 
1056
  Cardinal n;
 
1057
  Arg args[10];
 
1058
  Widget menuBar;
 
1059
  Widget cascade1, cascade2, cascade3;
 
1060
  Widget menuPane1, menuPane2;
 
1061
  Widget b1, b2, b3;
 
1062
 
 
1063
  menuBar   = XmCreateMenuBar(parent, "menuBar", NULL, 0);
 
1064
 
 
1065
  menuPane1 = XmCreatePulldownMenu(menuBar, "menuPane1", NULL, 0);
 
1066
  menuPane2 = XmCreatePulldownMenu(menuBar, "menuPane2", NULL, 0);
 
1067
 
 
1068
  b1 = XtCreateManagedWidget("b1", xmPushButtonWidgetClass, menuPane1, NULL,0);
 
1069
  XtAddCallback(b1, XmNactivateCallback, MenuCB, (XtPointer)MENU_QUIT);
 
1070
 
 
1071
  b2 = XtCreateManagedWidget("b2", xmPushButtonWidgetClass, menuPane2, NULL,0);
 
1072
  XtAddCallback(b2, XmNactivateCallback, MenuCB, (XtPointer)MENU_UPDATE);
 
1073
 
 
1074
  b3 = XtCreateManagedWidget("b3", xmPushButtonWidgetClass, menuPane2, NULL,0);
 
1075
  XtAddCallback(b3, XmNactivateCallback, MenuCB, (XtPointer)MENU_NEW);
 
1076
 
 
1077
  n = 0;
 
1078
  XtSetArg(args[n], XmNsubMenuId, menuPane1);  n++;
 
1079
  cascade1 = XmCreateCascadeButton(menuBar, "cascade1", args, n);
 
1080
  XtManageChild(cascade1);
 
1081
 
 
1082
  n = 0;
 
1083
  XtSetArg(args[n], XmNsubMenuId, menuPane2);  n++;
 
1084
  cascade2 = XmCreateCascadeButton(menuBar, "cascade2", args, n);
 
1085
  XtManageChild(cascade2);
 
1086
 
 
1087
  n = 0;
 
1088
  cascade3 = XmCreateCascadeButton(menuBar, "cascade3", args, n);
 
1089
  XtAddCallback(cascade3, XmNactivateCallback, MenuCB, (XtPointer)MENU_HELP);
 
1090
  XtManageChild(cascade3);
 
1091
 
 
1092
  n = 0;
 
1093
  XtSetArg(args[n], XmNmenuHelpWidget, cascade3);  n++;
 
1094
  XtSetValues(menuBar, args, n);
 
1095
 
 
1096
  XtManageChild(menuBar);
 
1097
}
 
1098
 
 
1099
 
 
1100
/*----------------------------------------------------------------*
 
1101
 |                             MenuCB                             |
 
1102
 *----------------------------------------------------------------*/
 
1103
static void
 
1104
MenuCB (Widget w, XtPointer clientData, XtPointer callData) 
 
1105
{
 
1106
 
 
1107
  switch ((long)clientData)
 
1108
    {
 
1109
    case MENU_UPDATE: DoUpdatePanner();  break;
 
1110
    case MENU_NEW:    DoAddDisplay();    break;
 
1111
    case MENU_QUIT:   DoQuit();          break;
 
1112
    case MENU_HELP:   DoHelp();          break;
 
1113
    }
 
1114
}
 
1115
 
 
1116
 
 
1117
 
 
1118
/*----------------------------------------------------------------*
 
1119
 |                         DoUpdatePanner                         |
 
1120
 *----------------------------------------------------------------*/
 
1121
static void
 
1122
DoUpdatePanner ()
 
1123
{
 
1124
  XClearArea(pInfoList[LOCAL].display,
 
1125
             XtWindow(pInfoList[DSP].canvas),
 
1126
             0, 0, 0, 0, False);
 
1127
 
 
1128
  DrawWindows(pInfoList);
 
1129
  DrawThumb(&pInfoList[DSP]);
 
1130
}
 
1131
 
 
1132
 
 
1133
/*----------------------------------------------------------------*
 
1134
 |                          DoAddDisplay                          |
 
1135
 *----------------------------------------------------------------*/
 
1136
static void
 
1137
DoAddDisplay ()
 
1138
{
 
1139
  static Widget dlog = NULL;
 
1140
  Arg           args[3];
 
1141
  int           n;
 
1142
 
 
1143
  if (dlog == NULL)
 
1144
    {
 
1145
      n = 0;
 
1146
      XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
 
1147
      dlog = XmCreatePromptDialog(pInfoList[LOCAL].shell, "promptDlog",
 
1148
                                  args, n);
 
1149
 
 
1150
      XtAddCallback(dlog, XmNokCallback, DoAddDisplayCB, pInfoList);
 
1151
      XtUnmanageChild( XmSelectionBoxGetChild (dlog, XmDIALOG_HELP_BUTTON) );
 
1152
    }
 
1153
  XtManageChild(dlog);
 
1154
}
 
1155
 
 
1156
 
 
1157
/*----------------------------------------------------------------*
 
1158
 |                              DoHelp                            |
 
1159
 *----------------------------------------------------------------*/
 
1160
static void
 
1161
DoHelp ()
 
1162
{
 
1163
  static Widget dlog = NULL;
 
1164
  Arg           args[3];
 
1165
  int           n;
 
1166
 
 
1167
  if (dlog == NULL)
 
1168
    {
 
1169
      dlog = XmCreateInformationDialog(pInfoList[LOCAL].shell, "messageDlog",
 
1170
                                        NULL, 0);
 
1171
      XtUnmanageChild( XmMessageBoxGetChild (dlog, XmDIALOG_HELP_BUTTON) );
 
1172
      XtUnmanageChild( XmMessageBoxGetChild (dlog, XmDIALOG_CANCEL_BUTTON) );
 
1173
    }
 
1174
 
 
1175
  XtManageChild(dlog);
 
1176
}
 
1177
 
 
1178
 
 
1179
/*----------------------------------------------------------------*
 
1180
 |                              DoQuit                            |
 
1181
 *----------------------------------------------------------------*/
 
1182
static void
 
1183
DoQuit ()
 
1184
{
 
1185
  XSync (pInfoList[LOCAL].display, False);
 
1186
  XCloseDisplay (pInfoList[LOCAL].display);
 
1187
 
 
1188
  exit(0);
 
1189
}
 
1190
 
 
1191
 
 
1192
 
 
1193
/*----------------------------------------------------------------*
 
1194
 |                         GetTimeStamp                           |
 
1195
 *----------------------------------------------------------------*/
 
1196
Time
 
1197
GetTimestamp (Display *dsp)
 
1198
{
 
1199
  XEvent            event;
 
1200
  XWindowAttributes attr;
 
1201
  Atom   timeProp = XInternAtom(dsp, "_MOTIF_CURRENT_TIME", False);
 
1202
  Window rwin     = DefaultRootWindow(dsp);
 
1203
 
 
1204
 
 
1205
  XGetWindowAttributes(dsp, rwin, &attr);
 
1206
 
 
1207
  if (! (attr.your_event_mask & PropertyChangeMask))
 
1208
    XSelectInput(dsp, rwin, attr.your_event_mask | PropertyChangeMask);
 
1209
  
 
1210
  XChangeProperty(dsp, rwin, timeProp, timeProp, 8, PropModeAppend, NULL, 0);
 
1211
  
 
1212
  XWindowEvent(dsp, rwin, PropertyChangeMask, &event);
 
1213
  
 
1214
  if (! (attr.your_event_mask & PropertyChangeMask))
 
1215
    XSelectInput(dsp, rwin, attr.your_event_mask);
 
1216
  
 
1217
  return(event.xproperty.time);
 
1218
}
 
1219
 
 
1220
 
 
1221
/*----------------------------------------------------------------*
 
1222
 |                      CheckPinnedState                          |
 
1223
 *----------------------------------------------------------------*/
 
1224
static void CheckPinnedState ()
 
1225
{
 
1226
  static int    panDx=0, panDy=-1;
 
1227
  XtPointer     msg, fulldata;
 
1228
  unsigned long size;
 
1229
  Window        rWin, child;
 
1230
  int           x, y;
 
1231
  unsigned int  width, height, bWidth, depth;
 
1232
  Time          time = GetTimestamp(pInfoList[LOCAL].display);
 
1233
 
 
1234
  if (pinnedState == VERIFIED)
 
1235
    return;
 
1236
 
 
1237
  panDy = -panDy;
 
1238
 
 
1239
  pinnedState = VERIFYING;
 
1240
 
 
1241
  /* Get position of the top-level shell */
 
1242
  XGetGeometry(pInfoList[LOCAL].display, XtWindow(pInfoList[LOCAL].shell),
 
1243
               &rWin, &x, &y, &width, &height, &bWidth, &depth);
 
1244
 
 
1245
  XTranslateCoordinates(pInfoList[LOCAL].display, XtWindow(pInfoList[LOCAL].shell),
 
1246
                        rWin, x, y, &origX, &origY, &child);
 
1247
  
 
1248
  size  = sizeof(CARD32);  /* panDx */
 
1249
  size += sizeof(CARD32);  /* panDy */
 
1250
  size += sizeof(CARD8);   /* config */
 
1251
 
 
1252
  msg = fulldata = (XtPointer) XtMalloc(sizeof(CARD8) * size);
 
1253
 
 
1254
  msg = PackCARD32(msg, panDx);
 
1255
  msg = PackCARD32(msg, panDy);
 
1256
  msg = PackCARD8(msg, True);
 
1257
 
 
1258
  if (! XmeNamedSink(pInfoList[LOCAL].utmShell,
 
1259
                     pInfoList[LOCAL].WM,
 
1260
                     XmCOPY,
 
1261
                     (XtPointer)fulldata,
 
1262
                     time)
 
1263
      )
 
1264
    printf("Error - UTM Transfer failed.\n");
 
1265
}
 
1266
 
 
1267
/*----------------------------------------------------------------*
 
1268
 |                      ShowPinStateWarning                       |
 
1269
 *----------------------------------------------------------------*/
 
1270
static void
 
1271
ShowPinStateWarning ()
 
1272
{
 
1273
  static Widget dlog = NULL;
 
1274
  Arg           args[3];
 
1275
  int           n;
 
1276
 
 
1277
  if (dlog == NULL)
 
1278
    {
 
1279
      dlog = XmCreateWarningDialog(pInfoList[LOCAL].shell, "warningDlog",
 
1280
                                        NULL, 0);
 
1281
      XtUnmanageChild( XmMessageBoxGetChild (dlog, XmDIALOG_HELP_BUTTON) );
 
1282
      XtUnmanageChild( XmMessageBoxGetChild (dlog, XmDIALOG_CANCEL_BUTTON) );
 
1283
    }
 
1284
 
 
1285
  XtManageChild(dlog);
 
1286
}
 
1287
 
 
1288
 
 
1289
/*----------------------------------------------------------------*
 
1290
 |                       HandleInitialExpose                      |
 
1291
 *----------------------------------------------------------------*/
 
1292
static void
 
1293
HandleInitialExpose (
 
1294
     Widget w,
 
1295
     XtPointer clientData,
 
1296
     XEvent *event,
 
1297
     Boolean *cont)
 
1298
{
 
1299
  XtRemoveEventHandler(w, ExposureMask, False, HandleInitialExpose, NULL);
 
1300
  CheckPinnedState();
 
1301
}