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
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/
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
15
* The Original Code is mozilla.org code.
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.
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>
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.
41
* ***** END LICENSE BLOCK ***** */
48
#include <X11/keysym.h>
49
#include <X11/keysymdef.h>
50
#include <X11/Xlocale.h>
54
#include "nsAppShell.h"
55
#include "nsKeyCode.h"
56
#include "nsWidgetsCID.h"
58
#include "nsIWidget.h"
59
#include "nsIEventQueueService.h"
60
#include "nsIServiceManager.h"
61
#include "nsICmdLineService.h"
62
#include "nsIDragService.h"
63
#include "nsIDragSessionXlib.h"
68
#define CHAR_BUF_SIZE 80
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);
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;
89
static PLHashTable *sQueueHashTable = nsnull;
90
static PLHashTable *sCountHashTable = nsnull;
91
static nsVoidArray *sEventQueueList = nsnull;
95
static const char *event_names[] =
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]))
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 )
149
nsAppShell::nsAppShell()
151
if (!sEventQueueList)
152
sEventQueueList = new nsVoidArray();
154
mEventQueue = nsnull;
157
NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell)
161
int xerror_handler( Display *display, XErrorEvent *ev )
163
/* this should _never_ be happen... but if this happens - debug mode or not - scream !!! */
165
XGetErrorText(display, ev->error_code, errmsg, sizeof(errmsg));
166
fprintf(stderr, "nsAppShellXlib: Warning (X Error) - %s\n", errmsg);
173
NS_METHOD nsAppShell::Create(int* bac, char ** bav)
175
/* Create the Xt Application context... */
176
if (mAppContext == nsnull) {
177
int argc = bac ? *bac : 0;
181
nsCOMPtr<nsICmdLineService> cmdLineArgs = do_GetService(kCmdLineServiceCID);
183
rv = cmdLineArgs->GetArgc(&argc);
185
argc = bac ? *bac : 0;
187
rv = cmdLineArgs->GetArgv(&argv);
192
char *displayName = nsnull;
193
Bool synchronize = False;
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;
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];
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);
215
for (i = 0; ++i < argc; ) {
216
if (COMPARE_FLAG1 ("sync", argv[i])) {
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;
228
for (i = 0; ++i < argc; ) {
229
if (COMPARE_FLAG1 ("install_colormap", argv[i])) {
230
xargs.install_colormap = True;
236
if (!setlocale (LC_ALL,""))
237
NS_WARNING("locale not supported by C library");
239
if (!XSupportsLocale ()) {
240
NS_WARNING("locale not supported by Xlib, locale set to C");
241
setlocale (LC_ALL, "C");
244
if (!XSetLocaleModifiers (""))
245
NS_WARNING("can not set locale modifiers");
247
XtToolkitInitialize();
248
mAppContext = XtCreateApplicationContext();
250
if (!(mDisplay = XtOpenDisplay (mAppContext, displayName,
251
"Mozilla5", "Mozilla5", nsnull, 0,
254
fprintf (stderr, "%s: unable to open display \"%s\"\n", argv[0], XDisplayName(displayName));
258
// Requires XSynchronize(mDisplay, True); To stop X buffering. Use this
259
// to make debugging easier. KenF
262
/* Set error handler which calls abort() - only usefull with an
263
* unbuffered X connection */
264
(void)XSetErrorHandler(xerror_handler);
266
NS_WARNING("running via unbuffered X connection.");
267
XSynchronize(mDisplay, True);
270
mXlib_rgb_handle = xxlib_rgb_create_handle(mDisplay, XDefaultScreenOfDisplay(mDisplay),
272
if (!mXlib_rgb_handle)
274
fprintf (stderr, "%s: unable to create Xlib context\n", argv[0]);
279
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsAppShell::Create(dpy=%p)\n",
285
NS_IMETHODIMP nsAppShell::Spinup()
289
#ifdef DEBUG_APPSHELL
290
printf("nsAppShell::Spinup()\n");
293
/* Get the event queue service */
294
nsCOMPtr<nsIEventQueueService> eventQService = do_GetService(kEventQueueServiceCID, &rv);
297
NS_WARNING("Could not obtain event queue service");
301
/* Get the event queue for the thread.*/
302
rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
304
/* If we got an event queue, use it. */
306
/* otherwise create a new event queue for the thread */
307
rv = eventQService->CreateThreadEventQueue();
309
NS_WARNING("Could not create the thread event queue");
313
/* Ask again nicely for the event queue now that we have created one. */
314
rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
316
NS_WARNING("Could not get the thread event queue");
321
ListenToEventQueue(mEventQueue, PR_TRUE);
326
/* must be a |XtInputCallbackProc| !! */
329
void HandleQueueXtProc(XtPointer ptr, int *source_fd, XtInputId* id)
331
nsIEventQueue *queue = (nsIEventQueue *)ptr;
332
queue->ProcessPendingEvents();
336
nsresult nsAppShell::Run()
338
if (mEventQueue == nsnull)
341
if (mEventQueue == nsnull) {
342
NS_WARNING("Cannot initialize the Event Queue");
343
return NS_ERROR_NOT_INITIALIZED;
348
/* process events. */
349
while (!DieAppShellDie)
351
XtAppNextEvent(mAppContext, &xevent);
353
if (XtDispatchEvent(&xevent) == False)
354
DispatchXEvent(&xevent);
356
if (XEventsQueued(mDisplay, QueuedAlready) == 0)
358
/* Flush the nsWindow's drawing queue */
359
nsWindow::UpdateIdle(nsnull);
367
NS_METHOD nsAppShell::Spindown()
370
ListenToEventQueue(mEventQueue, PR_FALSE);
371
mEventQueue->ProcessPendingEvents();
372
mEventQueue = nsnull;
378
#define NUMBER_HASH_KEY(_num) ((PLHashNumber) _num)
381
IntHashKey(PRInt32 key)
383
return NUMBER_HASH_KEY(key);
385
// wrapper so we can call a macro
387
static unsigned long getNextRequest (void *aClosure) {
388
return XNextRequest(nsAppShell::mDisplay);
392
NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
396
NS_WARNING("nsAppShell::ListenToEventQueue(): No event queue available.");
397
return NS_ERROR_NOT_INITIALIZED;
400
#ifdef DEBUG_APPSHELL
401
printf("ListenToEventQueue(%p, %d) this=%p\n", aQueue, aListen, this);
403
if (!sQueueHashTable) {
404
sQueueHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey,
405
PL_CompareValues, PL_CompareValues, 0, 0);
407
if (!sCountHashTable) {
408
sCountHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey,
409
PL_CompareValues, PL_CompareValues, 0, 0);
412
int queue_fd = aQueue->GetEventQueueSelectFD();
416
* but only if we arn't already in the table... */
417
if (!PL_HashTableLookup(sQueueHashTable, key)) {
420
/* set up our fds callbacks */
421
tag = (long)XtAppAddInput(mAppContext,
423
(XtPointer)(long)(XtInputReadMask),
425
(XtPointer)mEventQueue);
427
/* This hack would not be neccesary if we would have a hashtable function
428
* which returns success/failure in a separate var ...
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");
435
PL_HashTableAdd(sQueueHashTable, key, (void *)tag);
438
PLEventQueue *plqueue;
439
aQueue->GetPLEventQueue(&plqueue);
440
PL_RegisterEventIDFunc(plqueue, getNextRequest, 0);
441
sEventQueueList->AppendElement(plqueue);
444
/* Remove listener... */
445
PLEventQueue *plqueue;
446
aQueue->GetPLEventQueue(&plqueue);
447
PL_UnregisterEventIDFunc(plqueue);
448
sEventQueueList->RemoveElement(plqueue);
450
int tag = long(PL_HashTableLookup(sQueueHashTable, key));
452
tag -= NEVER_BE_ZERO_MAGIC;
453
XtRemoveInput((XtInputId)tag);
454
PL_HashTableRemove(sQueueHashTable, key);
461
/* Does nothing. Used by xp code with non-gtk expectations.
462
* this method will be removed once xp eventloops are working.
465
nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
467
aRealEvent = PR_FALSE;
473
nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
478
return NS_ERROR_NOT_INITIALIZED;
481
/* gisburn: Why do we have to call this explicitly ?
482
* I have registered a callback via XtAddAppInput() above...
484
mEventQueue->ProcessPendingEvents();
487
XtAppNextEvent(mAppContext, &xevent);
489
if (XtDispatchEvent(&xevent) == False)
490
DispatchXEvent(&xevent);
492
if (XEventsQueued(mDisplay, QueuedAlready) == 0)
494
/* Flush the nsWindow's drawing queue */
495
nsWindow::UpdateIdle(nsnull);
501
NS_METHOD nsAppShell::Exit()
503
DieAppShellDie = PR_TRUE;
507
nsAppShell::~nsAppShell()
511
void* nsAppShell::GetNativeData(PRUint32 aDataType)
517
nsAppShell::DispatchXEvent(XEvent *event)
520
widget = nsWidget::GetWidgetForWindow(event->xany.window);
522
// did someone pass us an x event for a window we don't own?
524
if (widget == nsnull)
527
// switch on the type of event
531
HandleExposeEvent(event, widget);
534
case ConfigureNotify:
535
// we need to make sure that this is the LAST of the
537
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("DispatchEvent: ConfigureNotify event for window 0x%lx %d %d %d %d\n",
538
event->xconfigure.window,
541
event->xconfigure.width,
542
event->xconfigure.height));
544
HandleConfigureNotifyEvent(event, widget);
550
HandleFocusInEvent(event, widget);
551
HandleButtonEvent(event, widget);
555
HandleMotionNotifyEvent(event, widget);
559
HandleKeyPressEvent(event, widget);
562
HandleKeyReleaseEvent(event, widget);
566
HandleFocusInEvent(event, widget);
570
HandleFocusOutEvent(event, widget);
574
HandleEnterEvent(event, widget);
578
HandleLeaveEvent(event, widget);
584
case VisibilityNotify:
585
HandleVisibilityNotifyEvent(event, widget);
588
HandleClientMessageEvent(event, widget);
590
case SelectionRequest:
591
HandleSelectionRequestEvent(event, widget);
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]));
602
nsAppShell::HandleMotionNotifyEvent(XEvent *event, nsWidget *aWidget)
605
HandleDragMotionEvent(event, aWidget);
608
nsMouseEvent mevent(NS_MOUSE_MOVE, aWidget);
611
mevent.point.x = event->xmotion.x;
612
mevent.point.y = event->xmotion.y;
614
mevent.isShift = mShiftDown;
615
mevent.isControl = mCtrlDown;
616
mevent.isAlt = mAltDown;
617
mevent.isMeta = mMetaDown;
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,
626
mevent.point.x = aEvent.xmotion.x;
627
mevent.point.y = aEvent.xmotion.y;
630
aWidget->DispatchMouseEvent(mevent);
635
nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget)
637
PRUint32 eventType = 0;
638
PRBool currentlyDragging = mDragging;
639
nsMouseScrollEvent scrollEvent(NS_MOUSE_SCROLL, aWidget);
641
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Button event for window 0x%lx button %d type %s\n",
643
event->xbutton.button,
644
(event->type == ButtonPress ? "ButtonPress" : "ButtonRelease")));
645
switch(event->type) {
647
switch(event->xbutton.button) {
649
eventType = NS_MOUSE_LEFT_BUTTON_DOWN;
653
eventType = NS_MOUSE_MIDDLE_BUTTON_DOWN;
656
/* look back into this in case anything actually needs a
657
* NS_MOUSE_RIGHT_BUTTON_DOWN */
658
eventType = NS_CONTEXTMENU;
662
scrollEvent.delta = (event->xbutton.button == 4) ? -3 : 3;
663
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
665
scrollEvent.point.x = event->xbutton.x;
666
scrollEvent.point.y = event->xbutton.y;
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);
680
switch(event->xbutton.button) {
682
eventType = NS_MOUSE_LEFT_BUTTON_UP;
683
mDragging = PR_FALSE;
686
eventType = NS_MOUSE_MIDDLE_BUTTON_UP;
689
eventType = NS_MOUSE_RIGHT_BUTTON_UP;
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();
707
// If we are waiting longer than 1 sec for the second click, this is not a
709
if (PR_Now() - mClickTime > 1000000)
712
if (event->type == ButtonPress) {
715
mClickTime = PR_Now();
717
mClickedButton = event->xbutton.button;
719
mClickTime = PR_Now() - mClickTime;
720
if ((mClickTime < 500000) && (mClickedButton == event->xbutton.button))
728
if (currentlyDragging && !mDragging)
729
HandleDragDropEvent(event, aWidget);
731
mevent.clickCount = mClicks;
732
NS_IF_ADDREF(aWidget);
733
aWidget->DispatchMouseEvent(mevent);
734
NS_IF_RELEASE(aWidget);
738
nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget)
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));
743
nsRect dirtyRect(event->xexpose.x, event->xexpose.y,
744
event->xexpose.width, event->xexpose.height);
746
/* compress expose events...
748
if (event->xexpose.count!=0) {
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);
757
aWidget->Invalidate(dirtyRect, PR_FALSE);
761
nsAppShell::HandleConfigureNotifyEvent(XEvent *event, nsWidget *aWidget)
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));
769
while (XCheckTypedWindowEvent(event->xany.display,
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)
777
*event = config_event;
779
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("DispatchEvent: Extra ConfigureNotify event for window 0x%lx %d %d %d %d\n",
780
event->xconfigure.window,
783
event->xconfigure.width,
784
event->xconfigure.height));
787
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("EVENT LOSSAGE\n"));
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
800
aWidget->OnResize(sevent);
802
delete sevent.windowSize;
805
PRUint32 nsConvertCharCodeToUnicode(XKeyEvent* xkey)
807
// The only Unicode specific at the moment is casting to PRUint32.
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
814
XComposeStatus compose;
815
unsigned char string_buf[CHAR_BUF_SIZE];
818
len = XLookupString(xkey, (char *)string_buf, CHAR_BUF_SIZE-1, &keysym, &compose);
822
if (xkey->state & ControlMask) {
823
if (xkey->state & ShiftMask) {
824
return (PRUint32)(string_buf[0] + 'A' - 1);
827
return (PRUint32)(string_buf[0] + 'a' - 1);
830
if (!isprint(string_buf[0])) {
834
return (PRUint32)(string_buf[0]);
839
nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget)
841
char string_buf[CHAR_BUF_SIZE];
843
Window focusWindow = None;
844
nsWidget *focusWidget = 0;
846
// figure out where the real focus should go...
847
focusWindow = nsWidget::GetFocusWindow();
848
if (focusWindow != None) {
849
focusWidget = nsWidget::GetWidgetForWindow(focusWindow);
852
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("KeyPress event for window 0x%lx ( 0x%lx focus window )\n",
856
// don't even bother...
857
if (focusWidget == 0) {
861
KeySym keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
862
event->xkey.keycode);
875
mShiftDown = PR_TRUE;
885
// Dont dispatch events for modifier keys pressed ALONE
886
if (nsKeyCode::KeyCodeIsModifier(event->xkey.keycode))
891
nsKeyEvent keyEvent(NS_KEY_DOWN, focusWidget);
893
XComposeStatus compose;
895
len = XLookupString(&event->xkey, string_buf, CHAR_BUF_SIZE-1, &keysym, &compose);
896
string_buf[len] = '\0';
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;
906
// printf("keysym = %x, keycode = %x, vk = %x\n",
908
// event->xkey.keycode,
909
// keyEvent.keyCode);
911
focusWidget->DispatchKeyEvent(keyEvent);
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;
922
focusWidget->DispatchKeyEvent(pressEvent);
927
nsAppShell::HandleKeyReleaseEvent(XEvent *event, nsWidget *aWidget)
929
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("KeyRelease event for window 0x%lx\n",
930
event->xkey.window));
932
KeySym keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
933
event->xkey.keycode);
942
mCtrlDown = PR_FALSE;
946
mShiftDown = PR_FALSE;
950
mMetaDown = PR_FALSE;
956
// Dont dispatch events for modifier keys pressed ALONE
957
if (nsKeyCode::KeyCodeIsModifier(event->xkey.keycode))
962
nsKeyEvent keyEvent(NS_KEY_UP, aWidget);
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;
975
aWidget->DispatchKeyEvent(keyEvent);
981
nsAppShell::HandleFocusInEvent(XEvent *event, nsWidget *aWidget)
983
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("FocusIn event for window 0x%lx\n",
984
event->xfocus.window));
985
nsFocusEvent focusEvent(NS_GOTFOCUS, aWidget);
988
aWidget->DispatchWindowEvent(focusEvent);
993
nsAppShell::HandleFocusOutEvent(XEvent *event, nsWidget *aWidget)
995
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("FocusOut event for window 0x%lx\n",
996
event->xfocus.window));
997
nsFocusEvent focusEvent(NS_LOSTFOCUS, aWidget);
1000
aWidget->DispatchWindowEvent(focusEvent);
1001
NS_RELEASE(aWidget);
1004
/* Identify pointer grab/ungrab events due to window manager activity */
1006
is_wm_ungrab_enter(XCrossingEvent *event)
1008
return (NotifyGrab == event->mode) &&
1009
((NotifyAncestor == event->detail) ||
1010
(NotifyVirtual == event->detail));
1014
is_wm_grab_leave(XCrossingEvent *event)
1016
return (NotifyGrab == event->mode) &&
1017
((NotifyAncestor == event->detail) ||
1018
(NotifyVirtual == event->detail));
1022
nsAppShell::HandleEnterEvent(XEvent *event, nsWidget *aWidget)
1024
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Enter event for window 0x%lx\n",
1025
event->xcrossing.window));
1027
if(is_wm_ungrab_enter(&event->xcrossing))
1031
HandleDragEnterEvent(event, aWidget);
1034
nsMouseEvent enterEvent(NS_MOUSE_ENTER, aWidget);
1036
enterEvent.time = event->xcrossing.time;
1037
enterEvent.point.x = nscoord(event->xcrossing.x);
1038
enterEvent.point.y = nscoord(event->xcrossing.y);
1040
// make sure this is in focus. This will do until I rewrite all the
1041
// focus routines. KenF
1042
aWidget->SetFocus();
1045
aWidget->DispatchWindowEvent(enterEvent);
1046
NS_RELEASE(aWidget);
1050
nsAppShell::HandleLeaveEvent(XEvent *event, nsWidget *aWidget)
1052
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Leave event for window 0x%lx\n",
1053
event->xcrossing.window));
1055
if(is_wm_grab_leave(&event->xcrossing))
1059
HandleDragLeaveEvent(event, aWidget);
1062
nsMouseEvent leaveEvent(NS_MOUSE_EXIT, aWidget);
1064
leaveEvent.time = event->xcrossing.time;
1065
leaveEvent.point.x = nscoord(event->xcrossing.x);
1066
leaveEvent.point.y = nscoord(event->xcrossing.y);
1069
aWidget->DispatchWindowEvent(leaveEvent);
1070
NS_RELEASE(aWidget);
1073
void nsAppShell::HandleVisibilityNotifyEvent(XEvent *event, nsWidget *aWidget)
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"));
1082
case VisibilityPartiallyObscured:
1083
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Partially Obscured\n"));
1085
case VisibilityUnobscured:
1086
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Unobscured\n"));
1089
aWidget->SetVisibility(event->xvisibility.state);
1092
void nsAppShell::HandleMapNotifyEvent(XEvent *event, nsWidget *aWidget)
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);
1100
void nsAppShell::HandleUnmapNotifyEvent(XEvent *event, nsWidget *aWidget)
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);
1108
void nsAppShell::HandleClientMessageEvent(XEvent *event, nsWidget *aWidget)
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");
1114
if (nsWidget::WMProtocolsInitialized) {
1115
if ((Atom)event->xclient.data.l[0] == nsWidget::WMDeleteWindow) {
1117
printf("got a delete window event\n");
1119
aWidget->OnDeleteWindow();
1124
void nsAppShell::HandleSelectionRequestEvent(XEvent *event, nsWidget *aWidget)
1126
nsGUIEvent ev(0, aWidget);
1128
ev.nativeMsg = (void *)event;
1130
aWidget->DispatchWindowEvent(ev);
1133
void nsAppShell::HandleDragMotionEvent(XEvent *event, nsWidget *aWidget) {
1134
PRBool currentlyDragging = PR_FALSE;
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(¤tlyDragging);
1146
if (currentlyDragging) {
1147
dragServiceXlib->UpdatePosition(event->xmotion.x, event->xmotion.y);
1149
nsMouseEvent mevent(NS_DRAGDROP_OVER, aWidget);
1150
mevent.point.x = event->xmotion.x;
1151
mevent.point.y = event->xmotion.y;
1154
aWidget->DispatchMouseEvent(mevent);
1155
NS_RELEASE(aWidget);
1159
void nsAppShell::HandleDragEnterEvent(XEvent *event, nsWidget *aWidget) {
1160
PRBool currentlyDragging = PR_FALSE;
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(¤tlyDragging);
1172
if (currentlyDragging) {
1173
nsMouseEvent enterEvent(NS_DRAGDROP_ENTER, aWidget);
1175
enterEvent.point.x = event->xcrossing.x;
1176
enterEvent.point.y = event->xcrossing.y;
1179
aWidget->DispatchWindowEvent(enterEvent);
1180
NS_RELEASE(aWidget);
1184
void nsAppShell::HandleDragLeaveEvent(XEvent *event, nsWidget *aWidget) {
1185
PRBool currentlyDragging = PR_FALSE;
1188
nsCOMPtr<nsIDragService> dragService( do_GetService(kCDragServiceCID, &rv) );
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(¤tlyDragging);
1199
if (currentlyDragging) {
1200
nsMouseEvent leaveEvent(NS_DRAGDROP_EXIT, aWidget);
1202
leaveEvent.point.x = event->xcrossing.x;
1203
leaveEvent.point.y = event->xcrossing.y;
1206
aWidget->DispatchWindowEvent(leaveEvent);
1207
NS_RELEASE(aWidget);
1211
void nsAppShell::HandleDragDropEvent(XEvent *event, nsWidget *aWidget) {
1212
PRBool currentlyDragging = PR_FALSE;
1215
nsCOMPtr<nsIDragService> dragService( do_GetService(kCDragServiceCID, &rv) );
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(¤tlyDragging);
1226
if (currentlyDragging) {
1227
nsMouseEvent mevent(NS_DRAGDROP_DROP, aWidget);
1228
mevent.point.x = event->xbutton.x;
1229
mevent.point.y = event->xbutton.y;
1231
NS_IF_ADDREF(aWidget);
1232
aWidget->DispatchMouseEvent(mevent);
1233
NS_IF_RELEASE(aWidget);
1235
dragService->EndDragSession();
1239
void nsAppShell::ForwardEvent(XEvent *event, nsWidget *aWidget)
1241
nsGUIEvent ev(0, aWidget);
1242
ev.nativeMsg = (void *)event;
1244
aWidget->DispatchWindowEvent(ev);