~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/widget/src/xlib/nsAppShell.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is 
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1998
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Peter Hartshorn <peter@igelaus.com.au>
 
24
 *   Ken Faulkner <faulkner@igelaus.com.au>
 
25
 *   Tony Tsui <tony@igelaus.com.au>
 
26
 *   Caspian Maclean <caspian@igelaus.com.au>
 
27
 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
 
28
 *
 
29
 * Alternatively, the contents of this file may be used under the terms of
 
30
 * either the GNU General Public License Version 2 or later (the "GPL"), or 
 
31
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
32
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
33
 * of those above. If you wish to allow use of your version of this file only
 
34
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
35
 * use your version of this file under the terms of the NPL, indicate your
 
36
 * decision by deleting the provisions above and replace them with the notice
 
37
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
38
 * the provisions above, a recipient may use your version of this file under
 
39
 * the terms of any one of the NPL, the GPL or the LGPL.
 
40
 *
 
41
 * ***** END LICENSE BLOCK ***** */
 
42
 
 
43
#include <stdlib.h>
 
44
#include <sys/time.h>
 
45
#include <unistd.h>
 
46
#include <ctype.h>
 
47
#include <errno.h>
 
48
#include <X11/keysym.h>
 
49
#include <X11/keysymdef.h>
 
50
#include <X11/Xlocale.h>
 
51
 
 
52
#include "nsWindow.h"
 
53
#include "nsWidget.h"
 
54
#include "nsAppShell.h"
 
55
#include "nsKeyCode.h"
 
56
#include "nsWidgetsCID.h"
 
57
 
 
58
#include "nsIWidget.h"
 
59
#include "nsIEventQueueService.h"
 
60
#include "nsIServiceManager.h"
 
61
#include "nsICmdLineService.h"
 
62
#include "nsIDragService.h"
 
63
#include "nsIDragSessionXlib.h"
 
64
#include "nsITimer.h"
 
65
 
 
66
#include "xlibrgb.h"
 
67
 
 
68
#define CHAR_BUF_SIZE 80
 
69
 
 
70
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
 
71
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
 
72
static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
 
73
 
 
74
/* nsAppShell static members */
 
75
Display *nsAppShell::mDisplay = nsnull;
 
76
XlibRgbHandle *nsAppShell::mXlib_rgb_handle = nsnull;
 
77
XtAppContext nsAppShell::mAppContext;
 
78
PRTime nsAppShell::mClickTime = 0;
 
79
PRInt16 nsAppShell::mClicks = 1;
 
80
PRUint16 nsAppShell::mClickedButton = 0;
 
81
PRPackedBool nsAppShell::mClicked = PR_FALSE;
 
82
PRPackedBool nsAppShell::mDragging  = PR_FALSE;
 
83
PRPackedBool nsAppShell::mAltDown   = PR_FALSE;
 
84
PRPackedBool nsAppShell::mShiftDown = PR_FALSE;
 
85
PRPackedBool nsAppShell::mCtrlDown  = PR_FALSE;
 
86
PRPackedBool nsAppShell::mMetaDown  = PR_FALSE;
 
87
PRPackedBool nsAppShell::DieAppShellDie = PR_FALSE;
 
88
 
 
89
static PLHashTable *sQueueHashTable = nsnull;
 
90
static PLHashTable *sCountHashTable = nsnull;
 
91
static nsVoidArray *sEventQueueList = nsnull;
 
92
 
 
93
 
 
94
// For debugging.
 
95
static const char *event_names[] = 
 
96
{
 
97
  "",
 
98
  "",
 
99
  "KeyPress",
 
100
  "KeyRelease",
 
101
  "ButtonPress",
 
102
  "ButtonRelease",
 
103
  "MotionNotify",
 
104
  "EnterNotify",
 
105
  "LeaveNotify",
 
106
  "FocusIn",
 
107
  "FocusOut",
 
108
  "KeymapNotify",
 
109
  "Expose",
 
110
  "GraphicsExpose",
 
111
  "NoExpose",
 
112
  "VisibilityNotify",
 
113
  "CreateNotify",
 
114
  "DestroyNotify",
 
115
  "UnmapNotify",
 
116
  "MapNotify",
 
117
  "MapRequest",
 
118
  "ReparentNotify",
 
119
  "ConfigureNotify",
 
120
  "ConfigureRequest",
 
121
  "GravityNotify",
 
122
  "ResizeRequest",
 
123
  "CirculateNotify",
 
124
  "CirculateRequest",
 
125
  "PropertyNotify",
 
126
  "SelectionClear",
 
127
  "SelectionRequest",
 
128
  "SelectionNotify",
 
129
  "ColormapNotify",
 
130
  "ClientMessage",
 
131
  "MappingNotify"
 
132
};
 
133
 
 
134
#define COMPARE_FLAG1( a,b) ((b)[0]=='-' && !strcmp((a), &(b)[1]))
 
135
#define COMPARE_FLAG2( a,b) ((b)[0]=='-' && (b)[1]=='-' && !strcmp((a), &(b)[2]))
 
136
#define COMPARE_FLAG12(a,b) ((b)[0]=='-' && !strcmp((a), (b)[1]=='-'?&(b)[2]:&(b)[1]))
 
137
 
 
138
#define ALL_EVENTS ( KeyPressMask | KeyReleaseMask | ButtonPressMask | \
 
139
                     ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | \
 
140
                     PointerMotionMask | PointerMotionHintMask | Button1MotionMask | \
 
141
                     Button2MotionMask | Button3MotionMask | \
 
142
                     Button4MotionMask | Button5MotionMask | ButtonMotionMask | \
 
143
                     KeymapStateMask | ExposureMask | VisibilityChangeMask | \
 
144
                     StructureNotifyMask | ResizeRedirectMask | \
 
145
                     SubstructureNotifyMask | SubstructureRedirectMask | \
 
146
                     FocusChangeMask | PropertyChangeMask | \
 
147
                     ColormapChangeMask | OwnerGrabButtonMask )
 
148
 
 
149
nsAppShell::nsAppShell()  
 
150
 
151
  if (!sEventQueueList)
 
152
    sEventQueueList = new nsVoidArray();
 
153
 
 
154
  mEventQueue = nsnull;
 
155
}
 
156
 
 
157
NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell)
 
158
 
 
159
PR_BEGIN_EXTERN_C
 
160
static 
 
161
int xerror_handler( Display *display, XErrorEvent *ev )
 
162
{
 
163
  /* this should _never_ be happen... but if this happens - debug mode or not - scream !!! */
 
164
  char errmsg[80];
 
165
  XGetErrorText(display, ev->error_code, errmsg, sizeof(errmsg));
 
166
  fprintf(stderr, "nsAppShellXlib: Warning (X Error) -  %s\n", errmsg);
 
167
  abort(); // die !!
 
168
  
 
169
  return 0;
 
170
}
 
171
PR_END_EXTERN_C
 
172
 
 
173
NS_METHOD nsAppShell::Create(int* bac, char ** bav)
 
174
{
 
175
  /* Create the Xt Application context... */
 
176
  if (mAppContext == nsnull) {
 
177
    int      argc = bac ? *bac : 0;
 
178
    char   **argv = bav;
 
179
    nsresult rv;
 
180
 
 
181
    nsCOMPtr<nsICmdLineService> cmdLineArgs = do_GetService(kCmdLineServiceCID);
 
182
    if (cmdLineArgs) {
 
183
      rv = cmdLineArgs->GetArgc(&argc);
 
184
      if(NS_FAILED(rv))
 
185
        argc = bac ? *bac : 0;
 
186
 
 
187
      rv = cmdLineArgs->GetArgv(&argv);
 
188
      if(NS_FAILED(rv))
 
189
        argv = bav;
 
190
    }
 
191
 
 
192
    char        *displayName    = nsnull;
 
193
    Bool         synchronize    = False;
 
194
    int          i;
 
195
    XlibRgbArgs  xargs;
 
196
    memset(&xargs, 0, sizeof(xargs));
 
197
    /* Use a "well-known" name that other modules can "look-up" this handle
 
198
     * via |xxlib_find_handle| ... */
 
199
    xargs.handle_name = XXLIBRGB_DEFAULT_HANDLE;
 
200
 
 
201
    for (i = 0; ++i < argc-1; ) {
 
202
      /* allow both --display and -display */
 
203
      if (COMPARE_FLAG12 ("display", argv[i])) {
 
204
        displayName=argv[i+1];
 
205
        break;
 
206
      }
 
207
    }
 
208
    for (i = 0; ++i < argc-1; ) {
 
209
      if (COMPARE_FLAG1 ("visual", argv[i])) {
 
210
        xargs.xtemplate_mask |= VisualIDMask;
 
211
        xargs.xtemplate.visualid = strtol(argv[i+1], NULL, 0);
 
212
        break;
 
213
      }
 
214
    }   
 
215
    for (i = 0; ++i < argc; ) {
 
216
      if (COMPARE_FLAG1 ("sync", argv[i])) {
 
217
        synchronize = True;
 
218
        break;
 
219
      }
 
220
    }
 
221
    for (i = 0; ++i < argc; ) {
 
222
      /* allow both --no-xshm and -no-xshm */
 
223
      if (COMPARE_FLAG12 ("no-xshm", argv[i])) {
 
224
        xargs.disallow_mit_shmem = True;
 
225
        break;
 
226
      }
 
227
    }    
 
228
    for (i = 0; ++i < argc; ) {
 
229
      if (COMPARE_FLAG1 ("install_colormap", argv[i])) {
 
230
        xargs.install_colormap = True;
 
231
        break;
 
232
      }
 
233
    }
 
234
    
 
235
    /* setup locale */
 
236
    if (!setlocale (LC_ALL,""))
 
237
      NS_WARNING("locale not supported by C library");
 
238
  
 
239
    if (!XSupportsLocale ()) {
 
240
      NS_WARNING("locale not supported by Xlib, locale set to C");
 
241
      setlocale (LC_ALL, "C");
 
242
    }
 
243
  
 
244
    if (!XSetLocaleModifiers (""))
 
245
      NS_WARNING("can not set locale modifiers");
 
246
 
 
247
    XtToolkitInitialize();
 
248
    mAppContext = XtCreateApplicationContext();
 
249
 
 
250
    if (!(mDisplay = XtOpenDisplay (mAppContext, displayName, 
 
251
                                    "Mozilla5", "Mozilla5", nsnull, 0, 
 
252
                                    &argc, argv))) 
 
253
    {
 
254
      fprintf (stderr, "%s:  unable to open display \"%s\"\n", argv[0], XDisplayName(displayName));
 
255
      exit (EXIT_FAILURE);
 
256
    }
 
257
    
 
258
    // Requires XSynchronize(mDisplay, True); To stop X buffering. Use this
 
259
    // to make debugging easier. KenF
 
260
    if (synchronize)
 
261
    {
 
262
      /* Set error handler which calls abort() - only usefull with an 
 
263
       * unbuffered X connection */
 
264
      (void)XSetErrorHandler(xerror_handler);
 
265
      
 
266
      NS_WARNING("running via unbuffered X connection.");
 
267
      XSynchronize(mDisplay, True);
 
268
    }
 
269
       
 
270
    mXlib_rgb_handle = xxlib_rgb_create_handle(mDisplay, XDefaultScreenOfDisplay(mDisplay),
 
271
                                               &xargs);
 
272
    if (!mXlib_rgb_handle)
 
273
    {
 
274
      fprintf (stderr, "%s:  unable to create Xlib context\n", argv[0]);
 
275
      exit (EXIT_FAILURE);
 
276
    }
 
277
  }
 
278
 
 
279
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsAppShell::Create(dpy=%p)\n",
 
280
         mDisplay));
 
281
 
 
282
  return NS_OK;
 
283
}
 
284
 
 
285
NS_IMETHODIMP nsAppShell::Spinup()
 
286
{
 
287
  nsresult rv = NS_OK;
 
288
 
 
289
#ifdef DEBUG_APPSHELL
 
290
  printf("nsAppShell::Spinup()\n");
 
291
#endif
 
292
 
 
293
  /* Get the event queue service */
 
294
  nsCOMPtr<nsIEventQueueService> eventQService = do_GetService(kEventQueueServiceCID, &rv);
 
295
 
 
296
  if (NS_FAILED(rv)) {
 
297
    NS_WARNING("Could not obtain event queue service");
 
298
    return rv;
 
299
  }
 
300
 
 
301
  /* Get the event queue for the thread.*/
 
302
  rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
 
303
  
 
304
  /* If we got an event queue, use it. */
 
305
  if (!mEventQueue) {
 
306
    /* otherwise create a new event queue for the thread */
 
307
    rv = eventQService->CreateThreadEventQueue();
 
308
    if (NS_FAILED(rv)) {
 
309
      NS_WARNING("Could not create the thread event queue");
 
310
      return rv;
 
311
    }
 
312
 
 
313
    /* Ask again nicely for the event queue now that we have created one. */
 
314
    rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
 
315
    if (NS_FAILED(rv)) {
 
316
      NS_WARNING("Could not get the thread event queue");
 
317
      return rv;
 
318
    }
 
319
  }
 
320
 
 
321
  ListenToEventQueue(mEventQueue, PR_TRUE);
 
322
 
 
323
  return rv;
 
324
}
 
325
 
 
326
/* must be a |XtInputCallbackProc| !! */
 
327
PR_BEGIN_EXTERN_C
 
328
static
 
329
void HandleQueueXtProc(XtPointer ptr, int *source_fd, XtInputId* id)
 
330
{
 
331
  nsIEventQueue *queue = (nsIEventQueue *)ptr;
 
332
  queue->ProcessPendingEvents();
 
333
}
 
334
PR_END_EXTERN_C
 
335
 
 
336
nsresult nsAppShell::Run()
 
337
{
 
338
  if (mEventQueue == nsnull)
 
339
    Spinup();
 
340
 
 
341
  if (mEventQueue == nsnull) {
 
342
    NS_WARNING("Cannot initialize the Event Queue");
 
343
    return NS_ERROR_NOT_INITIALIZED;
 
344
  }
 
345
               
 
346
  XEvent xevent;
 
347
  
 
348
  /* process events. */
 
349
  while (!DieAppShellDie) 
 
350
  {   
 
351
    XtAppNextEvent(mAppContext, &xevent);
 
352
  
 
353
    if (XtDispatchEvent(&xevent) == False)
 
354
      DispatchXEvent(&xevent);
 
355
    
 
356
    if (XEventsQueued(mDisplay, QueuedAlready) == 0)
 
357
    {
 
358
      /* Flush the nsWindow's drawing queue */
 
359
      nsWindow::UpdateIdle(nsnull);
 
360
    }
 
361
  }
 
362
  
 
363
  Spindown();
 
364
  return NS_OK;
 
365
}
 
366
 
 
367
NS_METHOD nsAppShell::Spindown()
 
368
{
 
369
  if (mEventQueue) {
 
370
    ListenToEventQueue(mEventQueue, PR_FALSE);
 
371
    mEventQueue->ProcessPendingEvents();
 
372
    mEventQueue = nsnull;
 
373
  }
 
374
 
 
375
  return NS_OK;
 
376
}
 
377
 
 
378
#define NUMBER_HASH_KEY(_num) ((PLHashNumber) _num)
 
379
 
 
380
static PLHashNumber
 
381
IntHashKey(PRInt32 key)
 
382
{
 
383
  return NUMBER_HASH_KEY(key);
 
384
}
 
385
// wrapper so we can call a macro
 
386
PR_BEGIN_EXTERN_C
 
387
static unsigned long getNextRequest (void *aClosure) {
 
388
  return XNextRequest(nsAppShell::mDisplay);
 
389
}
 
390
PR_END_EXTERN_C
 
391
 
 
392
NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
 
393
                                             PRBool aListen)
 
394
{
 
395
  if (!mEventQueue) {
 
396
    NS_WARNING("nsAppShell::ListenToEventQueue(): No event queue available.");
 
397
    return NS_ERROR_NOT_INITIALIZED;
 
398
  }
 
399
  
 
400
#ifdef DEBUG_APPSHELL
 
401
  printf("ListenToEventQueue(%p, %d) this=%p\n", aQueue, aListen, this);
 
402
#endif
 
403
  if (!sQueueHashTable) {
 
404
    sQueueHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey,
 
405
                                      PL_CompareValues, PL_CompareValues, 0, 0);
 
406
  }
 
407
  if (!sCountHashTable) {
 
408
    sCountHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey,
 
409
                                      PL_CompareValues, PL_CompareValues, 0, 0);
 
410
  }    
 
411
 
 
412
  int   queue_fd = aQueue->GetEventQueueSelectFD();
 
413
  void *key      = aQueue;
 
414
  if (aListen) {
 
415
    /* Add listener -
 
416
     * but only if we arn't already in the table... */
 
417
    if (!PL_HashTableLookup(sQueueHashTable, key)) {
 
418
      long tag;
 
419
        
 
420
      /* set up our fds callbacks */
 
421
      tag = (long)XtAppAddInput(mAppContext,
 
422
                                queue_fd,
 
423
                                (XtPointer)(long)(XtInputReadMask),
 
424
                                HandleQueueXtProc,
 
425
                                (XtPointer)mEventQueue);
 
426
 
 
427
/* This hack would not be neccesary if we would have a hashtable function
 
428
 * which returns success/failure in a separate var ...
 
429
 */
 
430
#define NEVER_BE_ZERO_MAGIC (54321) 
 
431
      tag += NEVER_BE_ZERO_MAGIC; /* be sure that |tag| is _never_ 0 */
 
432
      NS_ASSERTION(tag!=0, "tag is 0 while adding");
 
433
      
 
434
      if (tag) {
 
435
        PL_HashTableAdd(sQueueHashTable, key, (void *)tag);
 
436
      }
 
437
      
 
438
      PLEventQueue *plqueue;
 
439
      aQueue->GetPLEventQueue(&plqueue);
 
440
      PL_RegisterEventIDFunc(plqueue, getNextRequest, 0);
 
441
      sEventQueueList->AppendElement(plqueue);
 
442
    }
 
443
  } else {
 
444
    /* Remove listener... */   
 
445
    PLEventQueue *plqueue;
 
446
    aQueue->GetPLEventQueue(&plqueue);
 
447
    PL_UnregisterEventIDFunc(plqueue);
 
448
    sEventQueueList->RemoveElement(plqueue);
 
449
 
 
450
    int tag = long(PL_HashTableLookup(sQueueHashTable, key));
 
451
    if (tag) {
 
452
      tag -= NEVER_BE_ZERO_MAGIC;
 
453
      XtRemoveInput((XtInputId)tag);
 
454
      PL_HashTableRemove(sQueueHashTable, key);
 
455
    }  
 
456
  }
 
457
 
 
458
  return NS_OK;
 
459
}
 
460
 
 
461
/* Does nothing. Used by xp code with non-gtk expectations.
 
462
 * this method will be removed once xp eventloops are working.
 
463
 */
 
464
NS_METHOD
 
465
nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
 
466
{
 
467
  aRealEvent = PR_FALSE;
 
468
  aEvent     = nsnull;
 
469
 
 
470
  return NS_OK;
 
471
}
 
472
 
 
473
nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
 
474
{
 
475
  XEvent xevent;
 
476
  
 
477
  if (!mEventQueue)
 
478
    return NS_ERROR_NOT_INITIALIZED;
 
479
 
 
480
#if 1
 
481
  /* gisburn: Why do we have to call this explicitly ?
 
482
   * I have registered a callback via XtAddAppInput() above... 
 
483
   */  
 
484
  mEventQueue->ProcessPendingEvents();  
 
485
#endif
 
486
 
 
487
  XtAppNextEvent(mAppContext, &xevent);
 
488
    
 
489
  if (XtDispatchEvent(&xevent) == False)
 
490
    DispatchXEvent(&xevent);
 
491
   
 
492
  if (XEventsQueued(mDisplay, QueuedAlready) == 0)
 
493
  {
 
494
    /* Flush the nsWindow's drawing queue */
 
495
    nsWindow::UpdateIdle(nsnull);
 
496
  }
 
497
    
 
498
  return NS_OK;
 
499
}
 
500
 
 
501
NS_METHOD nsAppShell::Exit()
 
502
{
 
503
  DieAppShellDie = PR_TRUE;
 
504
  return NS_OK;
 
505
}
 
506
 
 
507
nsAppShell::~nsAppShell()
 
508
{
 
509
}
 
510
 
 
511
void* nsAppShell::GetNativeData(PRUint32 aDataType)
 
512
{
 
513
  return nsnull;
 
514
}
 
515
 
 
516
void
 
517
nsAppShell::DispatchXEvent(XEvent *event)
 
518
{
 
519
  nsWidget *widget;
 
520
  widget = nsWidget::GetWidgetForWindow(event->xany.window);
 
521
 
 
522
  // did someone pass us an x event for a window we don't own?
 
523
  // bad! bad!
 
524
  if (widget == nsnull)
 
525
    return;
 
526
 
 
527
  // switch on the type of event
 
528
  switch (event->type) 
 
529
  {
 
530
  case Expose:
 
531
    HandleExposeEvent(event, widget);
 
532
    break;
 
533
 
 
534
  case ConfigureNotify:
 
535
    // we need to make sure that this is the LAST of the
 
536
    // config events.
 
537
    PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("DispatchEvent: ConfigureNotify event for window 0x%lx %d %d %d %d\n",
 
538
                                         event->xconfigure.window,
 
539
                                         event->xconfigure.x, 
 
540
                                         event->xconfigure.y,
 
541
                                         event->xconfigure.width, 
 
542
                                         event->xconfigure.height));
 
543
 
 
544
    HandleConfigureNotifyEvent(event, widget);
 
545
 
 
546
    break;
 
547
 
 
548
  case ButtonPress:
 
549
  case ButtonRelease:
 
550
    HandleFocusInEvent(event, widget);
 
551
    HandleButtonEvent(event, widget);
 
552
    break;
 
553
 
 
554
  case MotionNotify:
 
555
    HandleMotionNotifyEvent(event, widget);
 
556
    break;
 
557
 
 
558
  case KeyPress:
 
559
    HandleKeyPressEvent(event, widget);
 
560
    break;
 
561
  case KeyRelease:
 
562
    HandleKeyReleaseEvent(event, widget);
 
563
    break;
 
564
 
 
565
  case FocusIn:
 
566
    HandleFocusInEvent(event, widget);
 
567
    break;
 
568
 
 
569
  case FocusOut:
 
570
    HandleFocusOutEvent(event, widget);
 
571
    break;
 
572
 
 
573
  case EnterNotify:
 
574
    HandleEnterEvent(event, widget);
 
575
    break;
 
576
 
 
577
  case LeaveNotify:
 
578
    HandleLeaveEvent(event, widget);
 
579
    break;
 
580
 
 
581
  case NoExpose:
 
582
    // these annoy me.
 
583
    break;
 
584
  case VisibilityNotify:
 
585
    HandleVisibilityNotifyEvent(event, widget);
 
586
    break;
 
587
  case ClientMessage:
 
588
    HandleClientMessageEvent(event, widget);
 
589
    break;
 
590
  case SelectionRequest:
 
591
    HandleSelectionRequestEvent(event, widget);
 
592
    break;
 
593
  default:
 
594
    PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Unhandled window event: Window 0x%lx Got a %s event\n",
 
595
                                         event->xany.window, event_names[event->type]));
 
596
 
 
597
    break;
 
598
  }
 
599
}
 
600
 
 
601
void
 
602
nsAppShell::HandleMotionNotifyEvent(XEvent *event, nsWidget *aWidget)
 
603
{
 
604
  if (mDragging) {
 
605
    HandleDragMotionEvent(event, aWidget);
 
606
  }
 
607
 
 
608
  nsMouseEvent mevent(NS_MOUSE_MOVE, aWidget);
 
609
  XEvent aEvent;
 
610
 
 
611
  mevent.point.x = event->xmotion.x;
 
612
  mevent.point.y = event->xmotion.y;
 
613
 
 
614
  mevent.isShift = mShiftDown;
 
615
  mevent.isControl = mCtrlDown;
 
616
  mevent.isAlt = mAltDown;
 
617
  mevent.isMeta = mMetaDown;
 
618
  
 
619
  Display * dpy = (Display *)aWidget->GetNativeData(NS_NATIVE_DISPLAY);
 
620
  Window win = (Window)aWidget->GetNativeData(NS_NATIVE_WINDOW);
 
621
  // We are only interested in the LAST (newest) location of the pointer
 
622
  while(XCheckWindowEvent(dpy,
 
623
                          win,
 
624
                          ButtonMotionMask,
 
625
                          &aEvent)) {
 
626
    mevent.point.x = aEvent.xmotion.x;
 
627
    mevent.point.y = aEvent.xmotion.y;
 
628
  }
 
629
  NS_ADDREF(aWidget);
 
630
  aWidget->DispatchMouseEvent(mevent);
 
631
  NS_RELEASE(aWidget);
 
632
}
 
633
 
 
634
void
 
635
nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget)
 
636
{
 
637
  PRUint32 eventType = 0;
 
638
  PRBool currentlyDragging = mDragging;
 
639
  nsMouseScrollEvent scrollEvent(NS_MOUSE_SCROLL, aWidget);
 
640
 
 
641
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Button event for window 0x%lx button %d type %s\n",
 
642
                                       event->xany.window,
 
643
                                       event->xbutton.button,
 
644
                                       (event->type == ButtonPress ? "ButtonPress" : "ButtonRelease")));
 
645
  switch(event->type) {
 
646
  case ButtonPress:
 
647
    switch(event->xbutton.button) {
 
648
    case 1:
 
649
      eventType = NS_MOUSE_LEFT_BUTTON_DOWN;
 
650
      mDragging = PR_TRUE;
 
651
      break;
 
652
    case 2:
 
653
      eventType = NS_MOUSE_MIDDLE_BUTTON_DOWN;
 
654
      break;
 
655
    case 3:
 
656
      /* look back into this in case anything actually needs a
 
657
       * NS_MOUSE_RIGHT_BUTTON_DOWN */
 
658
      eventType = NS_CONTEXTMENU;
 
659
      break;
 
660
    case 4:
 
661
    case 5:
 
662
      scrollEvent.delta = (event->xbutton.button == 4) ? -3 : 3;
 
663
      scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
 
664
 
 
665
      scrollEvent.point.x = event->xbutton.x;
 
666
      scrollEvent.point.y = event->xbutton.y;
 
667
 
 
668
      scrollEvent.isShift = mShiftDown;
 
669
      scrollEvent.isControl = mCtrlDown;
 
670
      scrollEvent.isAlt = mAltDown;
 
671
      scrollEvent.isMeta = mMetaDown;
 
672
      scrollEvent.time = PR_Now();
 
673
      NS_IF_ADDREF(aWidget);
 
674
      aWidget->DispatchWindowEvent(scrollEvent);
 
675
      NS_IF_RELEASE(aWidget);
 
676
      return;
 
677
    }
 
678
    break;
 
679
  case ButtonRelease:
 
680
    switch(event->xbutton.button) {
 
681
    case 1:
 
682
      eventType = NS_MOUSE_LEFT_BUTTON_UP;
 
683
      mDragging = PR_FALSE;
 
684
      break;
 
685
    case 2:
 
686
      eventType = NS_MOUSE_MIDDLE_BUTTON_UP;
 
687
      break;
 
688
    case 3:
 
689
      eventType = NS_MOUSE_RIGHT_BUTTON_UP;
 
690
      break;
 
691
    case 4:
 
692
    case 5:
 
693
      return;
 
694
    }
 
695
    break;
 
696
  }
 
697
 
 
698
  nsMouseEvent mevent(eventType, aWidget);
 
699
  mevent.isShift = mShiftDown;
 
700
  mevent.isControl = mCtrlDown;
 
701
  mevent.isAlt = mAltDown;
 
702
  mevent.isMeta = mMetaDown;
 
703
  mevent.point.x = event->xbutton.x;
 
704
  mevent.point.y = event->xbutton.y;
 
705
  mevent.time = PR_Now();
 
706
  
 
707
  // If we are waiting longer than 1 sec for the second click, this is not a
 
708
  // double click.
 
709
  if (PR_Now() - mClickTime > 1000000)
 
710
    mClicked = PR_FALSE;               
 
711
 
 
712
  if (event->type == ButtonPress) {
 
713
    if (!mClicked) {
 
714
      mClicked = PR_TRUE;
 
715
      mClickTime = PR_Now();
 
716
      mClicks = 1;
 
717
      mClickedButton = event->xbutton.button;
 
718
    } else {
 
719
      mClickTime = PR_Now() - mClickTime;
 
720
      if ((mClickTime < 500000) && (mClickedButton == event->xbutton.button))
 
721
        mClicks = 2;
 
722
      else
 
723
        mClicks = 1;
 
724
      mClicked = PR_FALSE;
 
725
    }
 
726
  }
 
727
 
 
728
  if (currentlyDragging && !mDragging)
 
729
    HandleDragDropEvent(event, aWidget);
 
730
 
 
731
  mevent.clickCount = mClicks;
 
732
  NS_IF_ADDREF(aWidget);
 
733
  aWidget->DispatchMouseEvent(mevent);
 
734
  NS_IF_RELEASE(aWidget);
 
735
}
 
736
 
 
737
void
 
738
nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget)
 
739
{
 
740
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Expose event for window 0x%lx %d %d %d %d\n", event->xany.window,
 
741
                                       event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height));
 
742
 
 
743
  nsRect dirtyRect(event->xexpose.x, event->xexpose.y, 
 
744
                   event->xexpose.width, event->xexpose.height);
 
745
 
 
746
  /* compress expose events...
 
747
   */
 
748
  if (event->xexpose.count!=0) {
 
749
     XEvent txe;
 
750
     do {
 
751
        XWindowEvent(event->xany.display, event->xany.window, ExposureMask, (XEvent *)&txe);
 
752
        dirtyRect.UnionRect(dirtyRect, nsRect(txe.xexpose.x, txe.xexpose.y, 
 
753
                                              txe.xexpose.width, txe.xexpose.height));
 
754
     } while (txe.xexpose.count>0);
 
755
  }
 
756
 
 
757
  aWidget->Invalidate(dirtyRect, PR_FALSE);
 
758
}
 
759
 
 
760
void
 
761
nsAppShell::HandleConfigureNotifyEvent(XEvent *event, nsWidget *aWidget)
 
762
{
 
763
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("ConfigureNotify event for window 0x%lx %d %d %d %d\n",
 
764
                                       event->xconfigure.window,
 
765
                                       event->xconfigure.x, event->xconfigure.y,
 
766
                                       event->xconfigure.width, event->xconfigure.height));
 
767
 
 
768
  XEvent    config_event;
 
769
  while (XCheckTypedWindowEvent(event->xany.display, 
 
770
                                event->xany.window, 
 
771
                                ConfigureNotify,
 
772
                                &config_event) == True) {
 
773
    // make sure that we don't get other types of events.  
 
774
    // StructureNotifyMask includes other kinds of events, too.
 
775
    if (config_event.type == ConfigureNotify) 
 
776
      {
 
777
        *event = config_event;
 
778
        
 
779
        PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("DispatchEvent: Extra ConfigureNotify event for window 0x%lx %d %d %d %d\n",
 
780
                                             event->xconfigure.window,
 
781
                                             event->xconfigure.x, 
 
782
                                             event->xconfigure.y,
 
783
                                             event->xconfigure.width, 
 
784
                                             event->xconfigure.height));
 
785
      }
 
786
    else {
 
787
      PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("EVENT LOSSAGE\n"));
 
788
    }
 
789
  }
 
790
 
 
791
  nsSizeEvent sevent(NS_SIZE, aWidget);
 
792
  sevent.windowSize = new nsRect (event->xconfigure.x, event->xconfigure.y,
 
793
                                  event->xconfigure.width, event->xconfigure.height);
 
794
  sevent.point.x = event->xconfigure.x;
 
795
  sevent.point.y = event->xconfigure.y;
 
796
  sevent.mWinWidth = event->xconfigure.width;
 
797
  sevent.mWinHeight = event->xconfigure.height;
 
798
  // XXX fix sevent.time
 
799
  NS_ADDREF(aWidget);
 
800
  aWidget->OnResize(sevent);
 
801
  NS_RELEASE(aWidget);
 
802
  delete sevent.windowSize;
 
803
}
 
804
 
 
805
PRUint32 nsConvertCharCodeToUnicode(XKeyEvent* xkey)
 
806
{
 
807
  // The only Unicode specific at the moment is casting to PRUint32.
 
808
 
 
809
  // For control characters convert from the event ascii code (e.g. 1 for
 
810
  // control-a) to the ascii code for the key, e.g., 'a' for
 
811
  // control-a.
 
812
 
 
813
  KeySym         keysym;
 
814
  XComposeStatus compose;
 
815
  unsigned char  string_buf[CHAR_BUF_SIZE];
 
816
  int            len = 0;
 
817
 
 
818
  len = XLookupString(xkey, (char *)string_buf, CHAR_BUF_SIZE-1, &keysym, &compose);
 
819
  if (0 == len)
 
820
    return 0;
 
821
 
 
822
  if (xkey->state & ControlMask) {
 
823
    if (xkey->state & ShiftMask) {
 
824
      return (PRUint32)(string_buf[0] + 'A' - 1);
 
825
    }
 
826
    else {
 
827
      return (PRUint32)(string_buf[0] + 'a' - 1);
 
828
    }
 
829
  }
 
830
  if (!isprint(string_buf[0])) {
 
831
    return 0;
 
832
  }
 
833
  else {
 
834
    return (PRUint32)(string_buf[0]);
 
835
  }
 
836
}
 
837
 
 
838
void
 
839
nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget)
 
840
{
 
841
  char      string_buf[CHAR_BUF_SIZE];
 
842
  int       len = 0;
 
843
  Window    focusWindow = None;
 
844
  nsWidget *focusWidget = 0;
 
845
 
 
846
  // figure out where the real focus should go...
 
847
  focusWindow = nsWidget::GetFocusWindow();
 
848
  if (focusWindow != None) {
 
849
    focusWidget = nsWidget::GetWidgetForWindow(focusWindow);
 
850
  }
 
851
 
 
852
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("KeyPress event for window 0x%lx ( 0x%lx focus window )\n",
 
853
                                       event->xkey.window,
 
854
                                       focusWindow));
 
855
 
 
856
  // don't even bother...
 
857
  if (focusWidget == 0) {
 
858
    return;
 
859
  }
 
860
 
 
861
  KeySym     keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
 
862
                                                        event->xkey.keycode);
 
863
 
 
864
  switch (keysym) {
 
865
    case XK_Alt_L:
 
866
    case XK_Alt_R:
 
867
      mAltDown = PR_TRUE;
 
868
      break;
 
869
    case XK_Control_L:
 
870
    case XK_Control_R:
 
871
      mCtrlDown = PR_TRUE;
 
872
      break;
 
873
    case XK_Shift_L:
 
874
    case XK_Shift_R:
 
875
      mShiftDown = PR_TRUE;
 
876
      break;
 
877
    case XK_Meta_L:
 
878
    case XK_Meta_R:
 
879
      mMetaDown = PR_TRUE;
 
880
      break;
 
881
    default:
 
882
      break;
 
883
  }
 
884
 
 
885
  // Dont dispatch events for modifier keys pressed ALONE
 
886
  if (nsKeyCode::KeyCodeIsModifier(event->xkey.keycode))
 
887
  {
 
888
    return;
 
889
  }
 
890
 
 
891
  nsKeyEvent keyEvent(NS_KEY_DOWN, focusWidget);
 
892
 
 
893
  XComposeStatus compose;
 
894
 
 
895
  len = XLookupString(&event->xkey, string_buf, CHAR_BUF_SIZE-1, &keysym, &compose);
 
896
  string_buf[len] = '\0';
 
897
 
 
898
  keyEvent.keyCode = nsKeyCode::ConvertKeySymToVirtualKey(keysym);
 
899
  keyEvent.time = event->xkey.time;
 
900
  keyEvent.isShift = (event->xkey.state & ShiftMask) ? PR_TRUE : PR_FALSE;
 
901
  keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0;
 
902
  keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0;
 
903
  // I think 'meta' is the same as 'alt' in X11. Is this OK for other systems?
 
904
  keyEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0;
 
905
 
 
906
  //  printf("keysym = %x, keycode = %x, vk = %x\n",
 
907
  //         keysym,
 
908
  //         event->xkey.keycode,
 
909
  //         keyEvent.keyCode);
 
910
 
 
911
  focusWidget->DispatchKeyEvent(keyEvent);
 
912
 
 
913
  nsKeyEvent pressEvent(NS_KEY_PRESS, focusWidget);
 
914
  pressEvent.keyCode = nsKeyCode::ConvertKeySymToVirtualKey(keysym);
 
915
  pressEvent.charCode = nsConvertCharCodeToUnicode(&event->xkey);
 
916
  pressEvent.time = event->xkey.time;
 
917
  pressEvent.isShift = (event->xkey.state & ShiftMask) ? PR_TRUE : PR_FALSE;
 
918
  pressEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0;
 
919
  pressEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0;
 
920
  pressEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0;
 
921
 
 
922
  focusWidget->DispatchKeyEvent(pressEvent);
 
923
 
 
924
}
 
925
 
 
926
void
 
927
nsAppShell::HandleKeyReleaseEvent(XEvent *event, nsWidget *aWidget)
 
928
{
 
929
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("KeyRelease event for window 0x%lx\n",
 
930
                                       event->xkey.window));
 
931
 
 
932
  KeySym     keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
 
933
                                                        event->xkey.keycode);
 
934
 
 
935
  switch (keysym) {
 
936
    case XK_Alt_L:
 
937
    case XK_Alt_R:
 
938
      mAltDown = PR_FALSE;
 
939
      break;
 
940
    case XK_Control_L:
 
941
    case XK_Control_R:
 
942
      mCtrlDown = PR_FALSE;
 
943
      break;
 
944
    case XK_Shift_L:
 
945
    case XK_Shift_R:
 
946
      mShiftDown = PR_FALSE;
 
947
      break;
 
948
    case XK_Meta_L:
 
949
    case XK_Meta_R:
 
950
      mMetaDown = PR_FALSE;
 
951
      break;
 
952
    default:
 
953
      break;
 
954
  }
 
955
 
 
956
  // Dont dispatch events for modifier keys pressed ALONE
 
957
  if (nsKeyCode::KeyCodeIsModifier(event->xkey.keycode))
 
958
  {
 
959
    return;
 
960
  }
 
961
 
 
962
  nsKeyEvent keyEvent(NS_KEY_UP, aWidget);
 
963
 
 
964
  keyEvent.keyCode = nsKeyCode::ConvertKeySymToVirtualKey(keysym);
 
965
  keyEvent.time = event->xkey.time;
 
966
  keyEvent.isShift = event->xkey.state & ShiftMask;
 
967
  keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0;
 
968
  keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0;
 
969
  keyEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0;
 
970
  keyEvent.point.x = event->xkey.x;
 
971
  keyEvent.point.y = event->xkey.y;
 
972
 
 
973
  NS_ADDREF(aWidget);
 
974
 
 
975
  aWidget->DispatchKeyEvent(keyEvent);
 
976
 
 
977
  NS_RELEASE(aWidget);
 
978
}
 
979
 
 
980
void
 
981
nsAppShell::HandleFocusInEvent(XEvent *event, nsWidget *aWidget)
 
982
{
 
983
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("FocusIn event for window 0x%lx\n",
 
984
                                       event->xfocus.window));
 
985
  nsFocusEvent focusEvent(NS_GOTFOCUS, aWidget);
 
986
  
 
987
  NS_ADDREF(aWidget);
 
988
  aWidget->DispatchWindowEvent(focusEvent);
 
989
  NS_RELEASE(aWidget);
 
990
}
 
991
 
 
992
void
 
993
nsAppShell::HandleFocusOutEvent(XEvent *event, nsWidget *aWidget)
 
994
{
 
995
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("FocusOut event for window 0x%lx\n",
 
996
                                       event->xfocus.window));
 
997
  nsFocusEvent focusEvent(NS_LOSTFOCUS, aWidget);
 
998
 
 
999
  NS_ADDREF(aWidget);
 
1000
  aWidget->DispatchWindowEvent(focusEvent);
 
1001
  NS_RELEASE(aWidget);
 
1002
}
 
1003
 
 
1004
/* Identify pointer grab/ungrab events due to window manager activity */
 
1005
static inline int
 
1006
is_wm_ungrab_enter(XCrossingEvent *event)
 
1007
{
 
1008
  return (NotifyGrab == event->mode) &&
 
1009
    ((NotifyAncestor == event->detail) ||
 
1010
     (NotifyVirtual == event->detail));
 
1011
}
 
1012
 
 
1013
static inline int
 
1014
is_wm_grab_leave(XCrossingEvent *event)
 
1015
{
 
1016
  return (NotifyGrab == event->mode) &&
 
1017
    ((NotifyAncestor == event->detail) ||
 
1018
     (NotifyVirtual == event->detail));
 
1019
}
 
1020
 
 
1021
void
 
1022
nsAppShell::HandleEnterEvent(XEvent *event, nsWidget *aWidget)
 
1023
{
 
1024
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Enter event for window 0x%lx\n",
 
1025
                                       event->xcrossing.window));
 
1026
 
 
1027
  if(is_wm_ungrab_enter(&event->xcrossing))
 
1028
    return;
 
1029
 
 
1030
  if (mDragging) {
 
1031
    HandleDragEnterEvent(event, aWidget);
 
1032
  }
 
1033
 
 
1034
  nsMouseEvent enterEvent(NS_MOUSE_ENTER, aWidget);
 
1035
 
 
1036
  enterEvent.time = event->xcrossing.time;
 
1037
  enterEvent.point.x = nscoord(event->xcrossing.x);
 
1038
  enterEvent.point.y = nscoord(event->xcrossing.y);
 
1039
  
 
1040
  // make sure this is in focus. This will do until I rewrite all the 
 
1041
  // focus routines. KenF
 
1042
  aWidget->SetFocus();
 
1043
 
 
1044
  NS_ADDREF(aWidget);
 
1045
  aWidget->DispatchWindowEvent(enterEvent);
 
1046
  NS_RELEASE(aWidget);
 
1047
}
 
1048
 
 
1049
void
 
1050
nsAppShell::HandleLeaveEvent(XEvent *event, nsWidget *aWidget)
 
1051
{
 
1052
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Leave event for window 0x%lx\n",
 
1053
                                       event->xcrossing.window));
 
1054
 
 
1055
  if(is_wm_grab_leave(&event->xcrossing))
 
1056
    return;
 
1057
 
 
1058
  if (mDragging) {
 
1059
    HandleDragLeaveEvent(event, aWidget);
 
1060
  }
 
1061
 
 
1062
  nsMouseEvent leaveEvent(NS_MOUSE_EXIT, aWidget);
 
1063
 
 
1064
  leaveEvent.time = event->xcrossing.time;
 
1065
  leaveEvent.point.x = nscoord(event->xcrossing.x);
 
1066
  leaveEvent.point.y = nscoord(event->xcrossing.y);
 
1067
  
 
1068
  NS_ADDREF(aWidget);
 
1069
  aWidget->DispatchWindowEvent(leaveEvent);
 
1070
  NS_RELEASE(aWidget);
 
1071
}
 
1072
 
 
1073
void nsAppShell::HandleVisibilityNotifyEvent(XEvent *event, nsWidget *aWidget)
 
1074
{
 
1075
#ifdef DEBUG
 
1076
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("VisibilityNotify event for window 0x%lx ",
 
1077
                                       event->xfocus.window));
 
1078
  switch(event->xvisibility.state) {
 
1079
  case VisibilityFullyObscured:
 
1080
    PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Fully Obscured\n"));
 
1081
    break;
 
1082
  case VisibilityPartiallyObscured:
 
1083
    PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Partially Obscured\n"));
 
1084
    break;
 
1085
  case VisibilityUnobscured:
 
1086
    PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Unobscured\n"));
 
1087
  }
 
1088
#endif
 
1089
  aWidget->SetVisibility(event->xvisibility.state);
 
1090
}
 
1091
 
 
1092
void nsAppShell::HandleMapNotifyEvent(XEvent *event, nsWidget *aWidget)
 
1093
{
 
1094
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("MapNotify event for window 0x%lx\n",
 
1095
                                       event->xmap.window));
 
1096
  // XXX set map status is gone now..
 
1097
  //  aWidget->SetMapStatus(PR_TRUE);
 
1098
}
 
1099
 
 
1100
void nsAppShell::HandleUnmapNotifyEvent(XEvent *event, nsWidget *aWidget)
 
1101
{
 
1102
  PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("UnmapNotifyEvent for window 0x%lx\n",
 
1103
                                       event->xunmap.window));
 
1104
  // XXX set map status is gone now..
 
1105
  //aWidget->SetMapStatus(PR_FALSE);
 
1106
}
 
1107
 
 
1108
void nsAppShell::HandleClientMessageEvent(XEvent *event, nsWidget *aWidget)
 
1109
{
 
1110
  // check to see if it's a WM_DELETE message
 
1111
#if defined(DEBUG_warren) || defined(DEBUG_quy)
 
1112
  printf("handling client message\n");
 
1113
#endif
 
1114
  if (nsWidget::WMProtocolsInitialized) {
 
1115
    if ((Atom)event->xclient.data.l[0] == nsWidget::WMDeleteWindow) {
 
1116
#ifdef DEBUG
 
1117
      printf("got a delete window event\n");
 
1118
#endif /* DEBUG */      
 
1119
      aWidget->OnDeleteWindow();
 
1120
    }
 
1121
  }
 
1122
}
 
1123
 
 
1124
void nsAppShell::HandleSelectionRequestEvent(XEvent *event, nsWidget *aWidget)
 
1125
{
 
1126
  nsGUIEvent ev(0, aWidget);
 
1127
 
 
1128
  ev.nativeMsg = (void *)event;
 
1129
 
 
1130
  aWidget->DispatchWindowEvent(ev);
 
1131
}
 
1132
 
 
1133
void nsAppShell::HandleDragMotionEvent(XEvent *event, nsWidget *aWidget) {
 
1134
  PRBool currentlyDragging = PR_FALSE;
 
1135
 
 
1136
  nsresult rv;
 
1137
  nsCOMPtr<nsIDragService> dragService( do_GetService(kCDragServiceCID, &rv) );
 
1138
  nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
 
1139
  if (NS_SUCCEEDED(rv)) {
 
1140
    dragServiceXlib = do_QueryInterface(dragService);
 
1141
    if (dragServiceXlib) {
 
1142
      dragServiceXlib->IsDragging(&currentlyDragging);
 
1143
    }
 
1144
  }
 
1145
 
 
1146
  if (currentlyDragging) {
 
1147
    dragServiceXlib->UpdatePosition(event->xmotion.x, event->xmotion.y);
 
1148
 
 
1149
    nsMouseEvent mevent(NS_DRAGDROP_OVER, aWidget);
 
1150
    mevent.point.x = event->xmotion.x;
 
1151
    mevent.point.y = event->xmotion.y;
 
1152
 
 
1153
    NS_ADDREF(aWidget);
 
1154
    aWidget->DispatchMouseEvent(mevent);
 
1155
    NS_RELEASE(aWidget);
 
1156
  }
 
1157
}
 
1158
 
 
1159
void nsAppShell::HandleDragEnterEvent(XEvent *event, nsWidget *aWidget) {
 
1160
  PRBool currentlyDragging = PR_FALSE;
 
1161
 
 
1162
  nsresult rv;
 
1163
  nsCOMPtr<nsIDragService> dragService( do_GetService(kCDragServiceCID, &rv) );
 
1164
  if (NS_SUCCEEDED(rv)) {
 
1165
    nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
 
1166
    dragServiceXlib = do_QueryInterface(dragService);
 
1167
    if (dragServiceXlib) {
 
1168
      dragServiceXlib->IsDragging(&currentlyDragging);
 
1169
    }
 
1170
  }
 
1171
 
 
1172
  if (currentlyDragging) {
 
1173
    nsMouseEvent enterEvent(NS_DRAGDROP_ENTER, aWidget);
 
1174
  
 
1175
    enterEvent.point.x = event->xcrossing.x;
 
1176
    enterEvent.point.y = event->xcrossing.y;
 
1177
  
 
1178
    NS_ADDREF(aWidget);
 
1179
    aWidget->DispatchWindowEvent(enterEvent);
 
1180
    NS_RELEASE(aWidget);
 
1181
  }
 
1182
}
 
1183
 
 
1184
void nsAppShell::HandleDragLeaveEvent(XEvent *event, nsWidget *aWidget) {
 
1185
  PRBool currentlyDragging = PR_FALSE;
 
1186
  
 
1187
  nsresult rv;
 
1188
  nsCOMPtr<nsIDragService> dragService( do_GetService(kCDragServiceCID, &rv) );
 
1189
 
 
1190
  // FIXME: Not sure if currentlyDragging is required. KenF
 
1191
  if (NS_SUCCEEDED(rv)) {
 
1192
    nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
 
1193
    dragServiceXlib = do_QueryInterface(dragService);
 
1194
    if (dragServiceXlib) {
 
1195
      dragServiceXlib->IsDragging(&currentlyDragging);
 
1196
    }
 
1197
  }
 
1198
 
 
1199
  if (currentlyDragging) {
 
1200
    nsMouseEvent leaveEvent(NS_DRAGDROP_EXIT, aWidget);
 
1201
  
 
1202
    leaveEvent.point.x = event->xcrossing.x;
 
1203
    leaveEvent.point.y = event->xcrossing.y;
 
1204
  
 
1205
    NS_ADDREF(aWidget);
 
1206
    aWidget->DispatchWindowEvent(leaveEvent);
 
1207
    NS_RELEASE(aWidget);
 
1208
  }
 
1209
}
 
1210
 
 
1211
void nsAppShell::HandleDragDropEvent(XEvent *event, nsWidget *aWidget) {
 
1212
  PRBool currentlyDragging = PR_FALSE;
 
1213
 
 
1214
  nsresult rv;
 
1215
  nsCOMPtr<nsIDragService> dragService( do_GetService(kCDragServiceCID, &rv) );
 
1216
 
 
1217
  // FIXME: Dont think the currentlyDragging check is required. KenF
 
1218
  if (NS_SUCCEEDED(rv)) {
 
1219
    nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
 
1220
    dragServiceXlib = do_QueryInterface(dragService);
 
1221
    if (dragServiceXlib) {
 
1222
      dragServiceXlib->IsDragging(&currentlyDragging);
 
1223
    }
 
1224
  }
 
1225
 
 
1226
  if (currentlyDragging) {
 
1227
    nsMouseEvent mevent(NS_DRAGDROP_DROP, aWidget);
 
1228
    mevent.point.x = event->xbutton.x;
 
1229
    mevent.point.y = event->xbutton.y;
 
1230
  
 
1231
    NS_IF_ADDREF(aWidget);
 
1232
    aWidget->DispatchMouseEvent(mevent);
 
1233
    NS_IF_RELEASE(aWidget);
 
1234
 
 
1235
    dragService->EndDragSession();
 
1236
  }
 
1237
}
 
1238
 
 
1239
void nsAppShell::ForwardEvent(XEvent *event, nsWidget *aWidget)
 
1240
{
 
1241
  nsGUIEvent ev(0, aWidget);
 
1242
  ev.nativeMsg = (void *)event;
 
1243
 
 
1244
  aWidget->DispatchWindowEvent(ev);
 
1245
}
 
1246