Updating xlib. Not part of the build

This commit is contained in:
quy%igelaus.com.au 2000-08-28 02:35:35 +00:00
Родитель 0a13534f94
Коммит 2020b8cdf8
14 изменённых файлов: 1728 добавлений и 863 удалений

Просмотреть файл

@ -27,6 +27,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = widget_xlib
IS_COMPONENT = 1
DIRS = window_service
@ -35,7 +36,9 @@ CPPSRCS = \
nsAppShell.cpp \
nsButton.cpp \
nsCheckButton.cpp \
nsClipboard.cpp \
nsComboBox.cpp \
nsDragService.cpp \
nsFileWidget.cpp \
nsKeyCode.cpp \
nsLabel.cpp \
@ -47,6 +50,7 @@ CPPSRCS = \
nsPopUpMenu.cpp \
nsRadioButton.cpp \
nsScrollBar.cpp \
nsSound.cpp \
nsTextAreaWidget.cpp \
nsTextHelper.cpp \
nsTextWidget.cpp \
@ -60,7 +64,7 @@ CPPSRCS = \
SHARED_LIBRARY_LIBS = $(DIST)/lib/libxpwidgets_s.a
ifndef MOZ_MONOLITHIC_TOOLKIT
EXTRA_DSO_LDOPTS += -L$(DIST)/bin -lxlibrgb $(MOZ_XLIB_LDFLAGS)
EXTRA_DSO_LDOPTS += -L$(DIST)/bin -lXt -lxlibrgb -lxlibxtbin -lXpm $(MOZ_XLIB_LDFLAGS)
else
EXTRA_DSO_LDOPTS += $(TK_LIBS)
endif

Просмотреть файл

@ -18,6 +18,8 @@
* Rights Reserved.
*
* Contributor(s):
* Peter Hartshorn <peter@igelaus.com.au>
* Ken Faulkner <faulkner@igelaus.com.au>
*/
#include <stdlib.h>
@ -25,14 +27,20 @@
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>
#include "nsWindow.h"
#include "nsWidget.h"
#include "nsAppShell.h"
#include "nsKeyCode.h"
#include "nsWidgetsCID.h"
#include "nsIWidget.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsIDragService.h"
#include "nsIDragSessionXlib.h"
#include "nsITimer.h"
#ifndef MOZ_MONOLITHIC_TOOLKIT
@ -45,6 +53,7 @@
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
#ifndef MOZ_MONOLITHIC_TOOLKIT
static NS_DEFINE_IID(kWindowServiceCID,NS_XLIB_WINDOW_SERVICE_CID);
@ -60,6 +69,17 @@ extern "C" void NS_ProcessTimeouts(void);
#endif /* !MOZ_MONOLITHIC_TOOLKIT */
PRBool nsAppShell::DieAppShellDie = PR_FALSE;
PRBool nsAppShell::mClicked = PR_FALSE;
PRTime nsAppShell::mClickTime = 0;
PRInt16 nsAppShell::mClicks = 1;
PRUint16 nsAppShell::mClickedButton = 0;
Display *nsAppShell::mDisplay = nsnull;
PRBool nsAppShell::mDragging = PR_FALSE;
PRBool nsAppShell::mAltDown = PR_FALSE;
PRBool nsAppShell::mShiftDown = PR_FALSE;
PRBool nsAppShell::mCtrlDown = PR_FALSE;
PRBool nsAppShell::mMetaDown = PR_FALSE;
// For debugging.
static char *event_names[] = {
@ -227,8 +247,8 @@ nsAppShell::nsAppShell()
NS_INIT_REFCNT();
mDispatchListener = 0;
mDisplay = nsnull;
mScreen = nsnull;
mEventQueue = nsnull;
}
nsresult nsAppShell::QueryInterface(const nsIID& aIID, void** aInstancePtr)
@ -247,18 +267,33 @@ nsresult nsAppShell::QueryInterface(const nsIID& aIID, void** aInstancePtr)
NS_METHOD nsAppShell::Create(int* argc, char ** argv)
{
char *mArgv[1];
int mArgc = 0;
XtAppContext app_context;
// Open the display
mDisplay = XOpenDisplay(NULL);
if (mDisplay == nsnull) {
mDisplay = XOpenDisplay(NULL);
if (mDisplay == NULL)
{
fprintf(stderr, "%s: Cannot connect to X server %s\n",
argv[0],
XDisplayName(NULL));
//XSynchronize(mDisplay, True);
// Requires XSynchronize(mDisplay, True); To stop X buffering. Use this
// to make debugging easier. KenF
if (mDisplay == NULL)
{
fprintf(stderr, "%s: Cannot connect to X server %s\n",
argv[0],
XDisplayName(NULL));
exit(1);
}
exit(1);
}
XtToolkitInitialize();
app_context = XtCreateApplicationContext();
XtDisplayInitialize(app_context, mDisplay, NULL, "Wrapper",
NULL, 0, &mArgc, mArgv);
}
// _Xdebug = 1;
mScreen = DefaultScreenOfDisplay(mDisplay);
@ -278,16 +313,11 @@ NS_METHOD nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener)
return NS_OK;
}
nsresult nsAppShell::Run()
NS_METHOD nsAppShell::Spinup()
{
nsresult rv;
NS_ADDREF_THIS();
nsresult rv = NS_OK;
nsIEventQueue *EQueue = nsnull;
int xlib_fd = -1;
int queue_fd = -1;
int max_fd;
fd_set select_set;
int select_retval;
// get the event queue service
rv = nsServiceManager::GetService(kEventQueueServiceCID,
@ -297,10 +327,9 @@ nsresult nsAppShell::Run()
NS_ASSERTION("Could not obtain event queue service", PR_FALSE);
return rv;
}
rv = mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &EQueue);
// If a queue already present use it.
if (EQueue)
goto done;
rv = mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &mEventQueue); // If a queue already present use it.
if (mEventQueue)
return NS_OK;
// Create the event queue for the thread
rv = mEventQueueService->CreateThreadEventQueue();
@ -309,28 +338,55 @@ nsresult nsAppShell::Run()
return rv;
}
//Get the event queue for the thread
rv = mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &EQueue);
if (NS_OK != rv) {
rv = mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &mEventQueue); if (NS_OK != rv) {
NS_ASSERTION("Could not obtain the thread event queue", PR_FALSE);
return rv;
}
done:
}
return NS_OK;
}
nsresult nsAppShell::Run()
{
nsresult rv = NS_OK;
int xlib_fd = -1;
int queue_fd = -1;
fd_set select_set;
int select_retval;
int max_fd;
XtInputMask mask;
XtAppContext app_context = XtDisplayToApplicationContext(mDisplay);
if (mEventQueue == nsnull)
Spinup();
if (mEventQueue == nsnull) {
NS_ASSERTION("Cannot initialize the Event Queue", PR_FALSE);
return NS_ERROR_NOT_INITIALIZED;
}
printf("Getting the xlib connection number.\n");
xlib_fd = ConnectionNumber(mDisplay);
// process events.
while (DieAppShellDie == PR_FALSE) {
// Dont think these should be here, but go with the flow. (KenF)
XEvent event;
struct timeval cur_time;
struct timeval *cur_time_ptr;
int please_run_timer_queue = 0;
struct timeval DelayTime ;
gettimeofday(&cur_time, NULL);
// set up our fds
queue_fd = EQueue->GetEventQueueSelectFD();
queue_fd = mEventQueue->GetEventQueueSelectFD();
// Get max of fd's
if (xlib_fd >= queue_fd) {
max_fd = xlib_fd + 1;
} else {
max_fd = queue_fd + 1;
}
FD_ZERO(&select_set);
// add the queue and the xlib connection to the select set
FD_SET(queue_fd, &select_set);
@ -347,62 +403,112 @@ nsresult nsAppShell::Run()
please_run_timer_queue = 1;
}
}
// if (cur_time_ptr)
//printf("select time: %ld %ld\n", cur_time_ptr->tv_sec, cur_time_ptr->tv_usec);
// note that we are passing in the timeout_ptr from above.
// if there are no timers, this will be null and this will
// block until hell freezes over
select_retval = select(max_fd, &select_set, NULL, NULL, cur_time_ptr);
// FIXME!!!
// Block for events. For moment, use a artificial timer to
// only block for a certain amount of time.
// When properly fixed, this delay should be cur_time_ptr
// and we need a way to detect an Xt event.
DelayTime.tv_sec = 0;
DelayTime.tv_usec = 100;
select_retval = select(max_fd, &select_set, NULL, NULL, &DelayTime);
if (select_retval == -1) {
printf("Select returned error: %s.\n", strerror(errno));
fprintf(stderr, "Select returned error: %s.\n", strerror(errno));
return NS_ERROR_FAILURE;
}
if (select_retval == 0) {
// the select timed out, process the timeout queue.
// printf("Timer ran out...\n");
please_run_timer_queue = 1;
}
// Xt event handler. (used for legacy plugins)
while ((mask = XtAppPending(app_context)) > 0) {
if (mask & XtIMXEvent) {
XtAppNextEvent(app_context, &event);
XtDispatchEvent(&event);
DispatchXEvent(&event);
} else {
XtAppProcessEvent(app_context, mask);
}
}
// check to see if there's data avilable for the queue
if (FD_ISSET(queue_fd, &select_set)) {
//printf("queue data available.\n");
EQueue->ProcessPendingEvents();
mEventQueue->ProcessPendingEvents();
}
// check to see if there's data avilable for
// xlib
// Xlib event dispatcher.
if (FD_ISSET(xlib_fd, &select_set)) {
while (XPending(mDisplay)) {
XNextEvent(mDisplay, &event);
DispatchXEvent(&event);
}
}
if (please_run_timer_queue) {
//printf("Running timer queue...\n");
CallProcessTimeoutsProc();
}
// make sure that any pending X requests are flushed.
// Flush the nsWindow's drawing queue
nsWindow::UpdateIdle(nsnull);
XFlush(mDisplay);
}
DieAppShellDie = PR_FALSE;
NS_IF_RELEASE(EQueue);
Spindown();
return rv;
}
NS_METHOD nsAppShell::Spindown()
{
NS_IF_RELEASE(mEventQueueService);
Release();
return rv;
if (mEventQueue) {
mEventQueue->ProcessPendingEvents();
NS_IF_RELEASE(mEventQueue);
}
return NS_OK;
}
NS_METHOD
nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{
XEvent *event;
if (XPending(mDisplay)) {
event = (XEvent *)malloc(sizeof(XEvent));
XNextEvent(mDisplay, event);
aRealEvent = PR_TRUE;
aEvent = event;
return NS_OK;
}
aRealEvent = PR_FALSE;
aEvent = nsnull;
return NS_OK;
}
nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
{
if (aEvent == 0) {
return NS_ERROR_FAILURE;
nsresult rv;
XEvent *event;
if (mEventQueue == nsnull) {
return NS_ERROR_NOT_INITIALIZED;
}
XEvent *event = (XEvent *)aEvent;
DispatchXEvent(event);
return NS_OK;
rv = mEventQueue->ProcessPendingEvents();
if (aRealEvent) {
event = (XEvent *)aEvent;
DispatchXEvent(event);
free(event);
}
CallProcessTimeoutsProc();
nsWindow::UpdateIdle(nsnull);
return rv;
}
NS_METHOD nsAppShell::Exit()
@ -426,6 +532,7 @@ nsAppShell::DispatchXEvent(XEvent *event)
nsWidget *widget;
widget = nsWidget::GetWidgetForWindow(event->xany.window);
// did someone pass us an x event for a window we don't own?
// bad! bad!
if (widget == nsnull)
@ -434,11 +541,11 @@ nsAppShell::DispatchXEvent(XEvent *event)
// switch on the type of event
switch (event->type)
{
case Expose:
HandleExposeEvent(event, widget);
case Expose:
HandleExposeEvent(event, widget);
break;
case ConfigureNotify:
case ConfigureNotify:
// we need to make sure that this is the LAST of the
// config events.
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("DispatchEvent: ConfigureNotify event for window 0x%lx %d %d %d %d\n",
@ -494,6 +601,9 @@ nsAppShell::DispatchXEvent(XEvent *event)
case ClientMessage:
HandleClientMessageEvent(event, widget);
break;
case SelectionRequest:
HandleSelectionRequestEvent(event, widget);
break;
default:
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Unhandled window event: Window 0x%lx Got a %s event\n",
event->xany.window, event_names[event->type]));
@ -506,12 +616,29 @@ void
nsAppShell::HandleMotionNotifyEvent(XEvent *event, nsWidget *aWidget)
{
nsMouseEvent mevent;
mevent.message = NS_MOUSE_MOVE;
XEvent aEvent;
if (mDragging) {
HandleDragMotionEvent(event, aWidget);
}
mevent.widget = aWidget;
mevent.eventStructType = NS_MOUSE_EVENT;
mevent.time = 0;
mevent.point.x = event->xmotion.x;
mevent.point.y = event->xmotion.y;
mevent.time = 0;
Display * dpy = (Display *)aWidget->GetNativeData(NS_NATIVE_DISPLAY);
Window win = (Window)aWidget->GetNativeData(NS_NATIVE_WINDOW);
// We are only interested in the LAST (newest) location of the pointer
while(XCheckWindowEvent(dpy,
win,
ButtonMotionMask,
&aEvent)) {
mevent.point.x = aEvent.xmotion.x;
mevent.point.y = aEvent.xmotion.y;
}
mevent.message = NS_MOUSE_MOVE;
mevent.eventStructType = NS_MOUSE_EVENT;
NS_ADDREF(aWidget);
aWidget->DispatchMouseEvent(mevent);
NS_RELEASE(aWidget);
@ -521,9 +648,12 @@ void
nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget)
{
nsMouseEvent mevent;
mevent.isShift = 0;
mevent.isControl = 0;
mevent.isShift = mShiftDown;
mevent.isControl = mCtrlDown;
mevent.isAlt = mAltDown;
mevent.isMeta = mMetaDown;
PRUint32 eventType = 0;
PRBool currentlyDragging = mDragging;
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Button event for window 0x%lx button %d type %s\n",
event->xany.window,
@ -534,6 +664,7 @@ nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget)
switch(event->xbutton.button) {
case 1:
eventType = NS_MOUSE_LEFT_BUTTON_DOWN;
mDragging = PR_TRUE;
break;
case 2:
eventType = NS_MOUSE_MIDDLE_BUTTON_DOWN;
@ -547,6 +678,7 @@ nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget)
switch(event->xbutton.button) {
case 1:
eventType = NS_MOUSE_LEFT_BUTTON_UP;
mDragging = PR_FALSE;
break;
case 2:
eventType = NS_MOUSE_MIDDLE_BUTTON_UP;
@ -558,23 +690,48 @@ nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget)
break;
}
mevent.message = eventType;
mevent.widget = aWidget;
mevent.eventStructType = NS_MOUSE_EVENT;
mevent.point.x = event->xbutton.x;
mevent.point.y = event->xbutton.y;
// XXX fix this. We need clicks
mevent.clickCount = 1;
mevent.time = 0;
NS_ADDREF(aWidget);
mevent.time = PR_Now();
// If we are waiting longer than 1 sec for the second click, this is not a
// double click.
if (PR_Now() - mClickTime > 1000000)
mClicked = PR_FALSE;
if (event->type == ButtonPress) {
if (!mClicked) {
mClicked = PR_TRUE;
mClickTime = PR_Now();
mClicks = 1;
mClickedButton = event->xbutton.button;
} else {
mClickTime = PR_Now() - mClickTime;
if ((mClickTime < 500000) && (mClickedButton == event->xbutton.button))
mClicks = 2;
else
mClicks = 1;
mClicked = PR_FALSE;
}
}
if (currentlyDragging && !mDragging) {
HandleDragDropEvent(event, aWidget);
}
mevent.message = eventType;
mevent.eventStructType = NS_MOUSE_EVENT;
mevent.clickCount = mClicks;
NS_IF_ADDREF(aWidget);
aWidget->DispatchMouseEvent(mevent);
NS_ADDREF(aWidget);
NS_IF_RELEASE(aWidget);
}
void
nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget)
{
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Expose event for window 0x%lx %d %d %d %d\n", event->xany.window,
event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height));
@ -592,6 +749,8 @@ nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget)
} while (txe.xexpose.count>0);
}
nsPaintEvent pevent;
pevent.message = NS_PAINT;
pevent.widget = aWidget;
@ -600,10 +759,13 @@ nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget)
// XXX fix this
pevent.time = 0;
//pevent.time = PR_Now();
//pevent.region = nsnull;
NS_ADDREF(aWidget);
aWidget->OnPaint(pevent);
NS_RELEASE(aWidget);
delete pevent.rect;
}
void
@ -678,6 +840,30 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget)
return;
}
KeySym keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
event->xkey.keycode);
switch (keysym) {
case XK_Alt_L:
case XK_Alt_R:
mAltDown = PR_TRUE;
break;
case XK_Control_L:
case XK_Control_R:
mCtrlDown = PR_TRUE;
break;
case XK_Shift_L:
case XK_Shift_R:
mShiftDown = PR_TRUE;
break;
case XK_Meta_L:
case XK_Meta_R:
mMetaDown = PR_TRUE;
break;
default:
break;
}
// Dont dispatch events for modifier keys pressed ALONE
if (nsKeyCode::KeyCodeIsModifier(event->xkey.keycode))
{
@ -686,8 +872,6 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget)
nsKeyEvent keyEvent;
KeySym keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
event->xkey.keycode);
XComposeStatus compose;
len = XLookupString(&event->xkey, string_buf, CHAR_BUF_SIZE, &keysym, &compose);
@ -697,8 +881,10 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget)
keyEvent.charCode = 0;
keyEvent.time = event->xkey.time;
keyEvent.isShift = event->xkey.state & ShiftMask;
keyEvent.isControl = event->xkey.state & ControlMask;
keyEvent.isAlt = event->xkey.state & Mod1Mask;
keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0;
keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0;
// I think 'meta' is the same as 'alt' in X11. Is this OK for other systems?
keyEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0;
keyEvent.point.x = 0;
keyEvent.point.y = 0;
keyEvent.message = NS_KEY_DOWN;
@ -716,8 +902,9 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget)
keyEvent.charCode = isprint(string_buf[0]) ? string_buf[0] : 0;
keyEvent.time = event->xkey.time;
keyEvent.isShift = event->xkey.state & ShiftMask;
keyEvent.isControl = event->xkey.state & ControlMask;
keyEvent.isAlt = event->xkey.state & Mod1Mask;
keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0;
keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0;
keyEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0;
keyEvent.point.x = 0;
keyEvent.point.y = 0;
keyEvent.message = NS_KEY_PRESS;
@ -734,6 +921,30 @@ nsAppShell::HandleKeyReleaseEvent(XEvent *event, nsWidget *aWidget)
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("KeyRelease event for window 0x%lx\n",
event->xkey.window));
KeySym keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
event->xkey.keycode);
switch (keysym) {
case XK_Alt_L:
case XK_Alt_R:
mAltDown = PR_FALSE;
break;
case XK_Control_L:
case XK_Control_R:
mCtrlDown = PR_FALSE;
break;
case XK_Shift_L:
case XK_Shift_R:
mShiftDown = PR_FALSE;
break;
case XK_Meta_L:
case XK_Meta_R:
mMetaDown = PR_FALSE;
break;
default:
break;
}
// Dont dispatch events for modifier keys pressed ALONE
if (nsKeyCode::KeyCodeIsModifier(event->xkey.keycode))
{
@ -741,15 +952,14 @@ nsAppShell::HandleKeyReleaseEvent(XEvent *event, nsWidget *aWidget)
}
nsKeyEvent keyEvent;
KeySym keysym = nsKeyCode::ConvertKeyCodeToKeySym(event->xkey.display,
event->xkey.keycode);
keyEvent.keyCode = nsKeyCode::ConvertKeySymToVirtualKey(keysym);
keyEvent.charCode = 0;
keyEvent.time = event->xkey.time;
keyEvent.isShift = event->xkey.state & ShiftMask;
keyEvent.isControl = event->xkey.state & ControlMask;
keyEvent.isAlt = event->xkey.state & Mod1Mask;
keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0;
keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0;
keyEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0;
keyEvent.point.x = event->xkey.x;
keyEvent.point.y = event->xkey.y;
keyEvent.message = NS_KEY_UP;
@ -780,6 +990,11 @@ nsAppShell::HandleFocusInEvent(XEvent *event, nsWidget *aWidget)
focusEvent.point.y = 0;
NS_ADDREF(aWidget);
// FIXME FIXME FIXME
// We now have to tell the widget that is has focus here, this was
// Previously done in cross platform code.
// FIXME FIXME FIXME
aWidget->SetFocus();
aWidget->DispatchWindowEvent(focusEvent);
NS_RELEASE(aWidget);
}
@ -791,7 +1006,7 @@ nsAppShell::HandleFocusOutEvent(XEvent *event, nsWidget *aWidget)
event->xfocus.window));
nsGUIEvent focusEvent;
focusEvent.message = NS_LOSTFOCUS;
focusEvent.message = NS_DEACTIVATE;
focusEvent.widget = aWidget;
focusEvent.eventStructType = NS_GUI_EVENT;
@ -812,19 +1027,21 @@ nsAppShell::HandleEnterEvent(XEvent *event, nsWidget *aWidget)
event->xcrossing.window));
nsMouseEvent enterEvent;
enterEvent.message = NS_MOUSE_ENTER;
if (mDragging) {
HandleDragEnterEvent(event, aWidget);
}
enterEvent.widget = aWidget;
enterEvent.eventStructType = NS_MOUSE_EVENT;
enterEvent.time = event->xcrossing.time;
enterEvent.point.x = nscoord(event->xcrossing.x);
enterEvent.point.y = nscoord(event->xcrossing.y);
enterEvent.message = NS_MOUSE_ENTER;
enterEvent.eventStructType = NS_MOUSE_EVENT;
NS_ADDREF(aWidget);
aWidget->DispatchWindowEvent(enterEvent);
NS_RELEASE(aWidget);
}
@ -836,19 +1053,21 @@ nsAppShell::HandleLeaveEvent(XEvent *event, nsWidget *aWidget)
nsMouseEvent leaveEvent;
leaveEvent.message = NS_MOUSE_EXIT;
if (mDragging) {
HandleDragLeaveEvent(event, aWidget);
}
leaveEvent.widget = aWidget;
leaveEvent.eventStructType = NS_MOUSE_EVENT;
leaveEvent.time = event->xcrossing.time;
leaveEvent.point.x = nscoord(event->xcrossing.x);
leaveEvent.point.y = nscoord(event->xcrossing.y);
leaveEvent.message = NS_MOUSE_EXIT;
leaveEvent.eventStructType = NS_MOUSE_EVENT;
NS_ADDREF(aWidget);
aWidget->DispatchWindowEvent(leaveEvent);
NS_RELEASE(aWidget);
}
@ -898,3 +1117,145 @@ void nsAppShell::HandleClientMessageEvent(XEvent *event, nsWidget *aWidget)
}
}
}
void nsAppShell::HandleSelectionRequestEvent(XEvent *event, nsWidget *aWidget)
{
nsGUIEvent ev;
ev.widget = (nsIWidget *)aWidget;
ev.nativeMsg = (void *)event;
aWidget->DispatchWindowEvent(ev);
}
void nsAppShell::HandleDragMotionEvent(XEvent *event, nsWidget *aWidget) {
nsMouseEvent mevent;
PRBool currentlyDragging = PR_FALSE;
nsCOMPtr<nsIDragService> dragService;
nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports**)&dragService);
if (NS_SUCCEEDED(rv)) {
dragServiceXlib = do_QueryInterface(dragService);
if (dragServiceXlib) {
dragServiceXlib->IsDragging(&currentlyDragging);
}
}
if (currentlyDragging) {
dragServiceXlib->UpdatePosition(event->xmotion.x, event->xmotion.y);
mevent.widget = aWidget;
mevent.point.x = event->xmotion.x;
mevent.point.y = event->xmotion.y;
mevent.message = NS_DRAGDROP_OVER;
mevent.eventStructType = NS_DRAGDROP_EVENT;
NS_ADDREF(aWidget);
aWidget->DispatchMouseEvent(mevent);
NS_RELEASE(aWidget);
}
}
void nsAppShell::HandleDragEnterEvent(XEvent *event, nsWidget *aWidget) {
nsMouseEvent enterEvent;
PRBool currentlyDragging = PR_FALSE;
nsCOMPtr<nsIDragService> dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports**)&dragService);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
dragServiceXlib = do_QueryInterface(dragService);
if (dragServiceXlib) {
dragServiceXlib->IsDragging(&currentlyDragging);
}
}
if (currentlyDragging) {
enterEvent.widget = aWidget;
enterEvent.point.x = event->xcrossing.x;
enterEvent.point.y = event->xcrossing.y;
enterEvent.message = NS_DRAGDROP_ENTER;
enterEvent.eventStructType = NS_DRAGDROP_EVENT;
NS_ADDREF(aWidget);
aWidget->DispatchWindowEvent(enterEvent);
NS_RELEASE(aWidget);
}
}
void nsAppShell::HandleDragLeaveEvent(XEvent *event, nsWidget *aWidget) {
nsMouseEvent leaveEvent;
PRBool currentlyDragging = PR_FALSE;
nsCOMPtr<nsIDragService> dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports**)&dragService);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
dragServiceXlib = do_QueryInterface(dragService);
if (dragServiceXlib) {
dragServiceXlib->IsDragging(&currentlyDragging);
}
}
if (currentlyDragging) {
leaveEvent.widget = aWidget;
leaveEvent.point.x = event->xcrossing.x;
leaveEvent.point.y = event->xcrossing.y;
leaveEvent.message = NS_DRAGDROP_EXIT;
leaveEvent.eventStructType = NS_DRAGDROP_EVENT;
NS_ADDREF(aWidget);
aWidget->DispatchWindowEvent(leaveEvent);
NS_RELEASE(aWidget);
}
}
void nsAppShell::HandleDragDropEvent(XEvent *event, nsWidget *aWidget) {
nsMouseEvent mevent;
PRBool currentlyDragging = PR_FALSE;
nsCOMPtr<nsIDragService> dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports**)&dragService);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDragSessionXlib> dragServiceXlib;
dragServiceXlib = do_QueryInterface(dragService);
if (dragServiceXlib) {
dragServiceXlib->IsDragging(&currentlyDragging);
}
}
if (currentlyDragging) {
mevent.widget = aWidget;
mevent.point.x = event->xbutton.x;
mevent.point.y = event->xbutton.y;
mevent.message = NS_DRAGDROP_DROP;
mevent.eventStructType = NS_DRAGDROP_EVENT;
NS_IF_ADDREF(aWidget);
aWidget->DispatchMouseEvent(mevent);
NS_IF_RELEASE(aWidget);
}
}
void nsAppShell::ForwardEvent(XEvent *event, nsWidget *aWidget)
{
nsGUIEvent ev;
ev.widget = (nsIWidget *)aWidget;
ev.nativeMsg = (void *)event;
aWidget->DispatchWindowEvent(ev);
}

Просмотреть файл

@ -25,6 +25,7 @@
#include "nsIAppShell.h"
#include "nsIEventQueueService.h"
#include "prtime.h"
class nsAppShell : public nsIAppShell
{
@ -38,8 +39,8 @@ class nsAppShell : public nsIAppShell
NS_IMETHOD Create(int* argc, char ** argv);
virtual nsresult Run();
NS_IMETHOD Spinup() { return NS_OK; }
NS_IMETHOD Spindown() { return NS_OK; }
NS_IMETHOD Spinup();
NS_IMETHOD Spindown();
NS_IMETHOD ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen)
{ return NS_OK; }
NS_IMETHOD GetNativeEvent(PRBool &aRealEvent, void *&aEvent);
@ -65,13 +66,29 @@ class nsAppShell : public nsIAppShell
static void HandleEnterEvent(XEvent *event, nsWidget *aWidget);
static void HandleLeaveEvent(XEvent *event, nsWidget *aWidget);
static void HandleClientMessageEvent(XEvent *event, nsWidget *aWidget);
static void HandleSelectionRequestEvent(XEvent *event, nsWidget *aWidget);
static void HandleDragMotionEvent(XEvent *event, nsWidget *aWidget);
static void HandleDragEnterEvent(XEvent *event, nsWidget *aWidget);
static void HandleDragLeaveEvent(XEvent *event, nsWidget *aWidget);
static void HandleDragDropEvent(XEvent *event, nsWidget *aWidget);
static void ForwardEvent(XEvent *event, nsWidget *aWidget);
static PRBool DieAppShellDie;
static PRBool mClicked;
static PRTime mClickTime;
static PRInt16 mClicks;
static PRUint16 mClickedButton;
static Display * mDisplay;
static PRBool mDragging;
static PRBool mAltDown;
static PRBool mShiftDown;
static PRBool mCtrlDown;
static PRBool mMetaDown;
protected:
nsIEventQueueService * mEventQueueService;
nsIEventQueue *mEventQueue;
Display * mDisplay;
Screen * mScreen;
};

Просмотреть файл

@ -17,428 +17,265 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Peter Hartshorn <peter@igelaus.com.au>
*/
/* TODO:
* Currently this only supports the transfer of TEXT! FIXME
*/
#include "nsClipboard.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "string.h"
#include "nsCOMPtr.h"
#include "nsFileSpec.h"
#include "nsCRT.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsIClipboardOwner.h"
#include "nsITransferable.h" // kTextMime
#include "nsIWidget.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsWidgetsCID.h"
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#include "nsTextFormatter.h"
#include "nsVoidArray.h"
#include "xlibrgb.h"
#include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h"
// unicode conversion
#define NS_IMPL_IDS
# include "nsIPlatformCharset.h"
#undef NS_IMPL_IDS
// The class statics:
//GtkWidget* nsClipboard::sWidget = nsnull;
nsCOMPtr<nsITransferable> nsClipboard::mTransferable = nsnull;
Window nsClipboard::sWindow;
Display *nsClipboard::sDisplay;
NS_IMPL_ADDREF_INHERITED(nsClipboard, nsBaseClipboard)
NS_IMPL_RELEASE_INHERITED(nsClipboard, nsBaseClipboard)
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
#if defined(DEBUG_akkana) || defined(DEBUG_mcafee) || defined(DEBUG_pavlov) || defined(DEBUG_blizzard)
#if defined(DEBUG_mcafee) || defined(DEBUG_pavlov)
#define DEBUG_CLIPBOARD
#endif
//-------------------------------------------------------------------------
//
// nsClipboard constructor
//
//-------------------------------------------------------------------------
nsClipboard::nsClipboard() : nsBaseClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::nsClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
NS_IMPL_ISUPPORTS1(nsClipboard, nsIClipboard);
//NS_INIT_REFCNT();
mIgnoreEmptyNotification = PR_FALSE;
mClipboardOwner = nsnull;
mTransferable = nsnull;
mSelectionData.data = nsnull;
mSelectionData.length = 0;
CreateInvisibleWindow();
nsClipboard::nsClipboard() {
NS_INIT_REFCNT();
sDisplay = xlib_rgb_get_display();
Init();
}
//-------------------------------------------------------------------------
//
// nsClipboard destructor
//
//-------------------------------------------------------------------------
nsClipboard::~nsClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::~nsClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
// Remove all our event handlers:
if (sWindow &&
XGetSelectionOwner(sDisplay, PRIMARY) == sWindow)
;
//gtk_selection_remove_all(sWidget);
// free the selection data, if any
nsClipboard::~nsClipboard() {
}
/**
* @param aIID The name of the class implementing the method
* @param _classiiddef The name of the #define symbol that defines the IID
* for the class (e.g. NS_ISUPPORTS_IID)
*
*/
nsresult nsClipboard::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
// Initialize the clipboard and create a nsWidget for communications
nsresult rv = NS_NOINTERFACE;
void nsClipboard::Init() {
sWidget = new nsWidget();
const nsRect rect(0,0,100,100);
if (aIID.Equals(NS_GET_IID(nsIClipboard))) {
*aInstancePtr = (void*) ((nsIClipboard*)this);
NS_ADDREF_THIS();
return NS_OK;
}
sWidget->Create((nsIWidget *)nsnull, rect, Callback,
(nsIDeviceContext *)nsnull, (nsIAppShell *)nsnull,
(nsIToolkit *)nsnull, (nsWidgetInitData *)nsnull);
sWindow = (Window)sWidget->GetNativeData(NS_NATIVE_WINDOW);
return rv;
XSelectInput(sDisplay, sWindow, 0x0fffff);
}
// This is the callback function for our nsWidget. It is given the
// XEvent from nsAppShell.
//
// Create an invisible window to own the selection
//
void nsClipboard::CreateInvisibleWindow(void)
{
}
nsEventStatus PR_CALLBACK nsClipboard::Callback(nsGUIEvent *event) {
XEvent *ev = (XEvent *)event->nativeMsg;
// Check the event type
if (ev->type == SelectionRequest) {
if (mTransferable == nsnull) {
fprintf(stderr, "nsClipboard::Callback: null transferable\n");
return nsEventStatus_eIgnore;
}
/**
*
*
*/
NS_IMETHODIMP nsClipboard::SetNativeClipboardData()
{
mIgnoreEmptyNotification = PR_TRUE;
// Get the data from the Transferable
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == mTransferable) {
printf(" SetNativeClipboardData: no transferable!\n");
return NS_ERROR_FAILURE;
}
// If we're already the selection owner, don't need to do anything,
// we'll already get the events:
if (sWindow && XGetSelectionOwner(sDisplay, PRIMARY) == sWindow)
return NS_OK;
// register as the selection owner:
if (XSetSelectionOwner(sDisplay, PRIMARY, sWindow, CurrentTime) != 0)
return NS_ERROR_FAILURE;
mIgnoreEmptyNotification = PR_FALSE;
return NS_OK;
}
//
// The blocking Paste routine
//
NS_IMETHODIMP
nsClipboard::GetNativeClipboardData(nsITransferable * aTransferable)
{
nsresult rv = NS_OK;
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::GetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == aTransferable) {
printf(" GetNativeClipboardData: Transferable is null!\n");
return NS_ERROR_FAILURE;
}
// Dunno why we need to do this, copying the win32 code ...
nsCOMPtr<nsITransferable> trans = do_QueryInterface(aTransferable);
if (!trans)
return rv;
//
// We can't call the copy callback when we're blocking on the paste callback;
// so if this app is already the selection owner, we need to copy our own
// data without going through the X server.
//
if (XGetSelectionOwner(sDisplay, PRIMARY) == sWindow)
{
// XXX only support text/plain for now
nsAutoString dataFlavor(kTextMime);
// Get data out of our existing transferable.
void *clipboardData;
char *dataFlavor = kUnicodeMime;
nsCOMPtr<nsISupports> genDataWrapper;
nsresult rv;
PRUint32 dataLength;
rv = mTransferable->GetTransferData(&dataFlavor,
&clipboardData,
void *data;
data = malloc(16384);
rv = mTransferable->GetTransferData(dataFlavor,
getter_AddRefs(genDataWrapper),
&dataLength);
if (NS_SUCCEEDED(rv))
rv = trans->SetTransferData(&dataFlavor,
clipboardData, dataLength);
return rv;
nsPrimitiveHelpers::CreateDataFromPrimitive(dataFlavor, genDataWrapper,
&data, dataLength);
if (NS_SUCCEEDED(rv) && data && dataLength) {
char *plainText = nsnull;
PRUnichar* unicodeData = NS_REINTERPRET_CAST(PRUnichar*, data);
PRInt32 plainLen = 0;
nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText(unicodeData,
dataLength/2,
&plainText,
&plainLen);
if (data) {
free(data);
data = plainText;
dataLength = plainLen;
}
// Set the window property to contain the data
XChangeProperty(sDisplay,
ev->xselectionrequest.requestor,
ev->xselectionrequest.property,
ev->xselectionrequest.target,
8, PropModeReplace,
(unsigned char *)data, dataLength);
// Send the requestor a SelectionNotify event
XEvent aEvent;
aEvent.type = SelectionNotify;
aEvent.xselection.serial = ev->xselectionrequest.serial;
aEvent.xselection.display = ev->xselectionrequest.display;
aEvent.xselection.requestor = ev->xselectionrequest.requestor;
aEvent.xselection.selection = ev->xselectionrequest.selection;
aEvent.xselection.target = ev->xselectionrequest.target;
aEvent.xselection.property = ev->xselectionrequest.property;
aEvent.xselection.time = CurrentTime;
XSendEvent(sDisplay, ev->xselectionrequest.requestor, 1, 0, &aEvent);
}
}
return nsEventStatus_eIgnore;
}
// Only support plaintext for now:
// What is "property" (set to None here)?
// Answer (from ORA Xlib book, p. 548):
// If the property field is not None, the owner should place the
// data resulting from converting the selection into the specified
// property on the requestor window, setting the type as before.
//
// This should queue a SelectionNotify event (see that callback)
XConvertSelection(sDisplay,
XA_PRIMARY, XA_STRING, None,
sWindow, CurrentTime);
// XXX we're not supposed to use CurrentTime, we're supposed to use
// the timestamp of the event causing us to request the selection.
// Alas, we don't have that information any more by the time we get here.
//
// We've told X what type to send, and we just have to wait
// for the callback saying that the data have been transferred.
//
// Set a flag saying that we're blocking waiting for the callback:
mBlocking = PR_TRUE;
#ifdef DEBUG_CLIPBOARD
printf("Waiting for the callback\n");
#endif /* DEBUG_CLIPBOARD */
// Now we need to wait until the callback comes in ...
// i is in case we get a runaway (yuck).
for (int i=0; mBlocking == PR_TRUE && i < 10000; ++i)
{
gtk_main_iteration_do(PR_TRUE);
}
#ifdef DEBUG_CLIPBOARD
printf("Got the callback: '%s', %d\n",
mSelectionData.data, mSelectionData.length);
#endif /* DEBUG_CLIPBOARD */
// We're back from the callback, no longer blocking:
mBlocking = PR_FALSE;
//
// Now we have data in mSelectionData.data.
// We just have to copy it to the transferable.
//
nsAutoString dataFlavor(kTextMime);
trans->SetTransferData(&dataFlavor,
mSelectionData.data, mSelectionData.length);
// Can't free the selection data -- the transferable just saves a pointer.
// But the transferable is responsible for freeing it, so we have to
// consider it freed now:
//g_free(mSelectionData.data);
mSelectionData.data = nsnull;
mSelectionData.length = 0;
NS_IMETHODIMP nsClipboard::SetData(nsITransferable *aTransferable,
nsIClipboardOwner *anOwner,
PRInt32 aWhichClipboard)
{
if (XSetSelectionOwner(sDisplay, XA_PRIMARY, sWindow, CurrentTime))
if (XGetSelectionOwner(sDisplay, XA_PRIMARY) != sWindow) {
fprintf(stderr, "nsClipboard::SetData: Cannot get ownership\n");
return NS_ERROR_FAILURE;
}
mTransferable = aTransferable;
return NS_OK;
}
//
// Called when the data from a paste comes in:
//
void
nsClipboard::SelectionReceivedCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData)
NS_IMETHODIMP nsClipboard::GetData(nsITransferable *aTransferable,
PRInt32 aWhcihClipboard)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionReceivedCB\n");
#endif /* DEBUG_CLIPBOARD */
unsigned char *data = 0;
unsigned long bytes = 0;
Bool only_if_exists;
Atom data_atom;
int i;
// ARGHH! GTK doesn't pass the arg to the callback, so we can't
// get "this" back! Until we solve this, get it from the service mgr:
nsresult rv;
NS_WITH_SERVICE(nsIClipboard, iclipboard, kCClipboardCID, &rv);
if (NS_FAILED(rv)) {
printf("Couldn't get clipboard service!\n");
return;
}
nsClipboard* clipboard = (nsClipboard*)iclipboard;
if (!clipboard) {
printf("couldn't convert nsIClipboard to nsClipboard\n");
return;
}
clipboard->SelectionReceiver(aWidget, aSelectionData);
}
void
nsClipboard::SelectionReceiver (Window aWindow,
GtkSelectionData *aSelectionData)
{
mBlocking = PR_FALSE;
if (aSelectionData->length < 0)
{
printf("Error retrieving selection: length was %d\n",
aSelectionData->length);
return;
}
switch (aSelectionData->type)
{
case XA_STRING:
mSelectionData = *aSelectionData;
mSelectionData.data = g_new(guchar, aSelectionData->length + 1);
memcpy(mSelectionData.data,
aSelectionData->data, aSelectionData->length);
// Null terminate in case anyone cares,
// and so we can print the string for debugging:
mSelectionData.data[aSelectionData->length] = '\0';
mSelectionData.length = aSelectionData->length;
return;
default:
printf("Can't convert type %s (%ld) to string\n",
gdk_atom_name (aSelectionData->type), aSelectionData->type);
return;
}
}
/**
* No-op.
*
*/
NS_IMETHODIMP nsClipboard::ForceDataToClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::ForceDataToClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == mTransferable) {
if (aTransferable == nsnull) {
fprintf(stderr, "nsClipboard::GetData: NULL transferable\n");
return NS_ERROR_FAILURE;
}
// If we currently own the selection, we will handle the paste
// internally, otherwise get the data from the X server
if (XGetSelectionOwner(sDisplay, XA_PRIMARY) == sWindow) {
char *dataFlavor = kUnicodeMime;
nsCOMPtr<nsISupports> genDataWrapper;
nsresult rv;
PRUint32 dataLength;
nsCOMPtr<nsITransferable> trans = do_QueryInterface(aTransferable);
if (!trans)
return NS_ERROR_FAILURE;
rv = mTransferable->GetTransferData(dataFlavor,
getter_AddRefs(genDataWrapper),
&dataLength);
if (NS_SUCCEEDED(rv)) {
rv = trans->SetTransferData(dataFlavor,
genDataWrapper,
dataLength);
}
} else {
data_atom = XInternAtom(sDisplay, "DATA_ATOM", only_if_exists = False);
data = (unsigned char *)malloc(16384);
XConvertSelection(sDisplay, XA_PRIMARY, XA_STRING, data_atom,
sWindow, CurrentTime);
// Wait for the SelectNotify event
mBlocking = PR_TRUE;
XEvent event;
for (i=0; (mBlocking == PR_TRUE) && i<10000; i++) {
if (XPending(sDisplay)) {
XNextEvent(sDisplay, &event);
if (event.type == SelectionNotify) {
mBlocking = PR_FALSE;
}
}
}
// If we got the event, mBlocking will still be true.
// So, get the data.
if (mBlocking == PR_FALSE) {
Atom type;
int format;
unsigned long items;
if (event.xselection.property != None) {
XGetWindowProperty(sDisplay, event.xselection.requestor,
event.xselection.property, 0, 16384/4,
0, AnyPropertyType,
&type, &format, &items, &bytes, &data);
bytes = strlen((char *)data);
}
}
mBlocking = PR_FALSE;
// Place the data in the transferable
PRInt32 length = bytes;
PRUnichar *testing = (PRUnichar *)malloc(strlen((char *)data)*2+1);
nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode((const char *)data,
length,
&testing,
&length);
nsCOMPtr<nsISupports> genDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData("text/unicode",
testing, length,
getter_AddRefs(genDataWrapper));
aTransferable->SetTransferData("text/unicode",
genDataWrapper,
bytes);
free(data);
free(testing);
}
return NS_OK;
}
//
// This is the callback which is called when another app
// requests the selection.
//
void nsClipboard::SelectionRequestCB(Window aWindow,
Atom selection,
Atom target,
Atom property,
Window requestor,
Time time)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionRequestCB\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *clipboard = (nsClipboard *)aData;
void *clipboardData;
PRUint32 dataLength;
nsresult rv;
// Make sure we have a transferable:
if (!clipboard->mTransferable) {
printf("Clipboard has no transferable!\n");
return;
}
// XXX hack, string-only for now.
// Create string data-flavor.
nsString dataFlavor (kTextMime);
// Get data out of transferable.
rv = clipboard->mTransferable->GetTransferData(&dataFlavor,
&clipboardData,
&dataLength);
// Currently we only offer the data in GDK_SELECTION_TYPE_STRING format.
if (NS_SUCCEEDED(rv) && clipboardData && dataLength > 0) {
gtk_selection_data_set(aSelectionData,
GDK_SELECTION_TYPE_STRING, 8,
(unsigned char *)clipboardData,
dataLength);
}
else
printf("Transferable didn't support the data flavor\n");
NS_IMETHODIMP nsClipboard::EmptyClipboard(PRInt32 aWhichClipboard) {
return NS_OK;
}
// Called when another app requests selection ownership:
void nsClipboard::SelectionClearCB(GtkWidget *widget,
GdkEventSelection *event,
gpointer data)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionClearCB\n");
#endif /* DEBUG_CLIPBOARD */
NS_IMETHODIMP nsClipboard::ForceDataToClipboard(PRInt32 aWhichClipboard) {
return NS_OK;
}
//
// The callback called after we've sent a convert selection request
// when the server calls us back with the data.
//
void
nsClipboard::SelectionNotifyCB(Window window,
Atom selection,
Atom target,
Atom property,
Time time)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionNotifyCB\n");
#endif /* DEBUG_CLIPBOARD */
// Un-block us, whether this works or not:
mBlocking = PR_FALSE;
if (property == None)
{
#ifdef DEBUG_CLIPBOARD
printf("Selection was refused!\n");
#endif /* DEBUG_CLIPBOARD */
return;
}
// I don't know what all these parameters are!
// So we're just throwing away the data.
do
{
long offset;
long length;
Atom actualType;
unsigned long nitems;
unsigned long bytesAfter;
unsigned char* propStr;
XGetWindowProperty(sDisplay, sWindow, property,
offset, length, FALSE, AnyPropertyType,
&actualType, &nitems, &bytesAfter, propStr);
} while (bytesAfter > 0);
// Now delete that window property to show we've gotten all the data:
XGetWindowProperty(sDisplay, sWindow, property,
offset, length, TRUE, AnyPropertyType,
&actualType, &nitems, &bytesAfter, propStr);
NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(nsISupportsArray *aFlavorList,
PRInt32 aWhichClipboard,
PRBool *_retval) {
*_retval = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsClipboard::SupportsSelectionClipboard(PRBool *_retval) {
*_retval = PR_TRUE;
return NS_OK;
}

Просмотреть файл

@ -17,23 +17,32 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Peter Hartshorn <peter@igelaus.com.au>
*/
#ifndef nsClipboard_h__
#define nsClipboard_h__
#include "nsBaseClipboard.h"
#include "nsIClipboard.h"
#include "nsITransferable.h"
#include "nsIClipboardOwner.h"
#include <nsCOMPtr.h>
#include "nsWidget.h"
#include "X11/X.h"
#include "X11/Xlib.h"
class nsITransferable;
class nsIClipboardOwner;
class nsIWidget;
/**
* Native Gtk Clipboard wrapper
* Native Xlib Clipboard wrapper
*/
class nsClipboard : public nsBaseClipboard
class nsClipboard : public nsIClipboard
{
public:
@ -41,52 +50,28 @@ public:
virtual ~nsClipboard();
//nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_ISUPPORTS
// nsIClipboard
NS_IMETHOD ForceDataToClipboard();
// nsIClipboard
NS_DECL_NSICLIPBOARD
protected:
NS_IMETHOD SetNativeClipboardData();
NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable);
void Init(void);
static nsEventStatus PR_CALLBACK Callback(nsGUIEvent *event);
PRBool mIgnoreEmptyNotification;
void CreateInvisibleWindow(void);
private:
static nsCOMPtr<nsITransferable> mTransferable;
PRBool mIgnoreEmptyNotification;
static Window *sWindow;
// Used for communicating pasted data
// from the asynchronous X routines back to a blocking paste:
GtkSelectionData mSelectionData;
PRBool mBlocking;
PRBool mBlocking;
void SelectionReceiver(GtkWidget *aWidget,
GtkSelectionData *aSelectionData);
static void SelectionGetCB(GtkWidget *widget,
GtkSelectionData *selection_data,
guint /*info*/,
guint /*time*/,
gpointer data);
static void SelectionClearCB(GtkWidget *widget,
GdkEventSelection *event,
gpointer data );
static void SelectionRequestCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData);
static void SelectionReceivedCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData);
static void SelectionNotifyCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData);
static Window sWindow;
nsWidget *sWidget;
static Display *sDisplay;
};

Просмотреть файл

@ -56,17 +56,27 @@ struct nsKeyConverter nsKeycodes[] =
{ NS_VK_CAPS_LOCK, XK_Caps_Lock},
{ NS_VK_ESCAPE, XK_Escape},
{ NS_VK_SPACE, XK_KP_Space},
{ NS_VK_PAGE_UP, XK_Page_Up},
{ NS_VK_PAGE_UP, XK_KP_Page_Up},
{ NS_VK_PAGE_DOWN, XK_Page_Down},
{ NS_VK_PAGE_DOWN, XK_KP_Page_Down},
{ NS_VK_END, XK_End},
{ NS_VK_END, XK_KP_End},
{ NS_VK_HOME, XK_Home},
{ NS_VK_HOME, XK_KP_Home},
{ NS_VK_LEFT, XK_Left},
{ NS_VK_LEFT, XK_KP_Left},
{ NS_VK_UP, XK_Up},
{ NS_VK_UP, XK_KP_Up},
{ NS_VK_RIGHT, XK_Right},
{ NS_VK_RIGHT, XK_KP_Right},
{ NS_VK_DOWN, XK_Down},
{ NS_VK_DOWN, XK_KP_Down},
{ NS_VK_PRINTSCREEN, XK_Print},
{ NS_VK_INSERT, XK_Insert},
{ NS_VK_INSERT, XK_KP_Insert},
{ NS_VK_DELETE, XK_Delete},
{ NS_VK_DELETE, XK_KP_Delete},
{ NS_VK_0, XK_0},
{ NS_VK_1, XK_1},
{ NS_VK_2, XK_2},

Просмотреть файл

@ -88,6 +88,7 @@ NS_METHOD nsScrollbar::SetPosition(PRUint32 aPos)
{
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetPosition()\n"));
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("Scroll to %d\n", aPos));
// mPosition = (PRUint32)((float)aPos / (float)mRequestedSize.height * (float)mMaxRange);
mPosition = aPos;
CalcBarBounds();
LayoutBar();
@ -167,6 +168,9 @@ PRBool nsScrollbar::OnScroll(PRUint32 scrollCode, int cPos)
case NS_SCROLLBAR_PAGE_PREV:
result = PrevPage();
break;
case NS_SCROLLBAR_POS:
result = SetPosition(cPos);
break;
default:
break;
}
@ -194,6 +198,14 @@ PRBool nsScrollbar::DispatchMouseEvent(nsMouseEvent &aEvent)
// check to see if this was on the main window.
switch (aEvent.message) {
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
if (mIsVertical == PR_TRUE) {
OnScroll(NS_SCROLLBAR_POS, aEvent.point.y);
}
else {
OnScroll(NS_SCROLLBAR_POS, aEvent.point.x);
}
break;
case NS_MOUSE_LEFT_BUTTON_DOWN:
if (mIsVertical == PR_TRUE) {
if (aEvent.point.y < mBarBounds.y) {

Просмотреть файл

@ -24,6 +24,11 @@
#include "nsGUIEvent.h"
#include "plevent.h"
// Static Thread Local Storage index of the toolkit object associated with
// a given thread...
static PRUintn gToolkitTLSIndex = 0;
nsToolkit::nsToolkit()
{
NS_INIT_REFCNT();
@ -40,3 +45,35 @@ NS_METHOD nsToolkit::Init(PRThread *aThread)
{
return NS_OK;
}
NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult)
{
nsIToolkit* toolkit = nsnull;
nsresult rv = NS_OK;
PRStatus status;
// Create the TLS (Thread Local Storage) index the first time through
if (gToolkitTLSIndex == 0)
{
status = PR_NewThreadPrivateIndex(&gToolkitTLSIndex, NULL);
if (PR_FAILURE == status)
{
rv = NS_ERROR_FAILURE;
}
}
if (NS_SUCCEEDED(rv))
{
toolkit = (nsIToolkit*)PR_GetThreadPrivate(gToolkitTLSIndex);
// Create a new toolkit for this thread
if (!toolkit)
{
fprintf(stderr, "Creating a new nsIToolkit!\n");
}
else
fprintf(stderr, "No need to create a new nsIToolkit!\n");
}
return NS_OK;
}

Просмотреть файл

@ -18,6 +18,9 @@
* Rights Reserved.
*
* Contributor(s):
* Peter Hartshorn <peter@igelaus.com.au>
* Ken Faulkner <faulkner@igelaus.com.au>
* Quy Tonthat <quy@igelaus.com.au>
*/
#include "nsWidget.h"
@ -35,6 +38,8 @@
#include "xlibrgb.h"
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
PRLogModuleInfo *XlibWidgetsLM = PR_NewLogModule("XlibWidgets");
PRLogModuleInfo *XlibScrollingLM = PR_NewLogModule("XlibScrolling");
@ -49,9 +54,9 @@ nsHashtable *nsWidget::gsWindowList = nsnull;
//nsXlibWindowCallback *nsWidget::mWindowCallback = nsnull;
/* static */ nsXlibWindowCallback nsWidget::gsWindowCreateCallback = nsnull;
/* static */ nsXlibWindowCallback nsWidget::gsWindowDestroyCallback = nsnull;
/* static */ nsXlibEventDispatcher nsWidget::gsEventDispatcher = nsnull;
nsXlibWindowCallback nsWidget::gsWindowCreateCallback = nsnull;
nsXlibWindowCallback nsWidget::gsWindowDestroyCallback = nsnull;
nsXlibEventDispatcher nsWidget::gsEventDispatcher = nsnull;
// this is for implemention the WM_PROTOCOL code
PRBool nsWidget::WMProtocolsInitialized = PR_FALSE;
@ -72,7 +77,7 @@ public:
}
~nsWindowKey(void) {
}
PRUint32 HashValue(void) const {
PRUint32 HashCode(void) const {
return (PRUint32)mKey;
}
@ -85,7 +90,7 @@ public:
}
};
nsWidget::nsWidget() : nsBaseWidget()
nsWidget::nsWidget() // : nsBaseWidget()
{
mPreferredWidth = 0;
mPreferredHeight = 0;
@ -109,18 +114,42 @@ nsWidget::nsWidget() : nsBaseWidget()
mVisibility = VisibilityFullyObscured; // this is an X constant.
mWindowType = eWindowType_child;
mBorderStyle = eBorderStyle_default;
// added KenF
mIsDestroying = PR_FALSE;
mOnDestroyCalled = PR_FALSE;
mListenForResizes = PR_FALSE; // If we're native we need to listen.
mMapped = PR_FALSE;
mUpdateArea = do_CreateInstance(kRegionCID);
if (mUpdateArea) {
mUpdateArea->Init();
mUpdateArea->SetTo(0, 0, 0, 0);
}
}
// FIXME:
// Heavily modifying so functionally similar as gtk version. KenF
nsWidget::~nsWidget()
{
DestroyNative();
//mIsDestroying = TRUE;
if (mBaseWindow)
Destroy();
}
void
nsWidget::DestroyNative(void)
{
// This is handled in nsDrawingSurfaceXlib for now
#if 0
if (mGC)
XFreeGC(mDisplay, mGC);
#endif
if (mBaseWindow) {
XDestroyWindow(mDisplay, mBaseWindow);
@ -128,6 +157,12 @@ nsWidget::DestroyNative(void)
}
}
// Stub in nsWidget, real in nsWindow. KenF
void * nsWidget::CheckParent(long ThisWindow)
{
return (void*)-1;
}
NS_IMETHODIMP nsWidget::Create(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
@ -136,7 +171,9 @@ NS_IMETHODIMP nsWidget::Create(nsIWidget *aParent,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData)
{
mParentWidget = aParent;
// Do adding in SWC() KenF
//mParentWidget = aParent;
//NS_IF_ADDREF(mParentWidget); // KenF FIXME
return(StandardWidgetCreate(aParent, aRect, aHandleEventFunction,
aContext, aAppShell, aToolkit, aInitData,
@ -159,6 +196,7 @@ NS_IMETHODIMP nsWidget::Create(nsNativeWidget aParent,
static NS_DEFINE_IID(kWindowServiceCID,NS_XLIB_WINDOW_SERVICE_CID);
static NS_DEFINE_IID(kWindowServiceIID,NS_XLIB_WINDOW_SERVICE_IID);
/* FIXME: This is a VERY messy function. Must rewrite this!!!! */
nsresult
nsWidget::StandardWidgetCreate(nsIWidget *aParent,
const nsRect &aRect,
@ -169,34 +207,50 @@ nsWidget::StandardWidgetCreate(nsIWidget *aParent,
nsWidgetInitData *aInitData,
nsNativeWidget aNativeParent)
{
Window parent;
unsigned long ValueMask;
XSetWindowAttributes SetWinAttr;
Window parent=nsnull;
mDisplay = xlib_rgb_get_display();
mScreen = xlib_rgb_get_screen();
mVisual = xlib_rgb_get_visual();
mDepth = xlib_rgb_get_depth();
// Pinched from GTK. Does checking here for window type. KenF
nsIWidget *baseParent = (aInitData &&
(aInitData->mWindowType == eWindowType_dialog ||
aInitData->mWindowType == eWindowType_toplevel)) ?
nsnull : aParent;
// set up the BaseWidget parts.
BaseCreate(aParent, aRect, aHandleEventFunction, aContext,
BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
aAppShell, aToolkit, aInitData);
// Keep copy of parent. Do a add here????
// Can never follow the rules properly!!!!!
// FIXME KenF
mParentWidget = aParent;
NS_IF_ADDREF(mParentWidget);
// check to see if the parent is there...
if (nsnull != aParent) {
parent = ((aParent) ? (Window)aParent->GetNativeData(NS_NATIVE_WINDOW) : nsnull);
} else {
if (aNativeParent) {
parent = (Window)aNativeParent;
mListenForResizes = PR_TRUE;
} else if (aParent) {
parent = (Window)aParent->GetNativeData(NS_NATIVE_WINDOW);
}
// if there's no parent, make the parent the root window.
if (parent == 0) {
// if (parent == nsnull) {
if (((aInitData) && (aInitData->mWindowType == eWindowType_dialog)) ||
(parent == nsnull)) {
parent = RootWindowOfScreen(mScreen);
mIsToplevel = PR_TRUE;
}
// set the bounds
mBounds = aRect;
mRequestedSize = aRect;
#ifndef MOZ_MONOLITHIC_TOOLKIT
nsIXlibWindowService * xlibWindowService = nsnull;
@ -210,18 +264,27 @@ nsWidget::StandardWidgetCreate(nsIWidget *aParent,
{
xlibWindowService->GetWindowCreateCallback(&gsWindowCreateCallback);
xlibWindowService->GetWindowDestroyCallback(&gsWindowDestroyCallback);
// NS_ASSERTION(nsnull != gsWindowCreateCallback,"Window create callback is null.");
// NS_ASSERTION(nsnull != gsWindowDestroyCallback,"Window destroy callback is null.");
xlibWindowService->SetEventDispatcher((nsXlibEventDispatcher) nsAppShell::DispatchXEvent);
xlibWindowService->SetEventDispatcher((nsXlibEventDispatcher)
nsAppShell::DispatchXEvent);
NS_RELEASE(xlibWindowService);
}
#endif /* !MOZ_MONOLITHIC_TOOLKIT */
// call the native create function
CreateNative(parent, mBounds);
// Make sure a popup has the proper attributes for a popup.
// ie, not changed by WM, and not changed in anyway.
// (use of override redirect)
if (((aInitData) && (aInitData->mWindowType == eWindowType_popup)) ||
(parent == nsnull)) {
ValueMask = CWOverrideRedirect;
SetWinAttr.override_redirect = True;
XChangeWindowAttributes(mDisplay, mBaseWindow, ValueMask, &SetWinAttr);
parent = RootWindowOfScreen(mScreen);
mIsToplevel = PR_TRUE;
}
// set up our wm hints if it's appropriate
if (mIsToplevel == PR_TRUE) {
SetUpWMHints();
@ -230,9 +293,32 @@ nsWidget::StandardWidgetCreate(nsIWidget *aParent,
return NS_OK;
}
// FIXME: Being heavily modified so functionally similar to gtk version.
// (just a test) KenF
NS_IMETHODIMP nsWidget::Destroy()
{
// Dont reenter.
if (mIsDestroying)
return NS_OK;
mIsDestroying = TRUE;
nsBaseWidget::Destroy();
NS_IF_RELEASE(mParentWidget); //????
if (mBaseWindow) {
DestroyNative();
//mBaseWindow = NULL;
if (PR_FALSE == mOnDestroyCalled)
OnDestroy();
mBaseWindow = NULL;
mEventCallback = nsnull;
}
return NS_OK;
}
NS_IMETHODIMP nsWidget::ConstrainPosition(PRInt32 *aX, PRInt32 *aY)
@ -264,6 +350,7 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth,
if (aWidth <= 0) {
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** width is %d, fixing.\n", aWidth));
aWidth = 1;
}
if (aHeight <= 0) {
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** height is %d, fixing.\n", aHeight));
@ -277,6 +364,7 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth,
} else {
XResizeWindow(mDisplay, mBaseWindow, aWidth, aHeight);
}
return NS_OK;
}
@ -327,6 +415,7 @@ NS_IMETHODIMP nsWidget::Enable(PRBool bState)
NS_IMETHODIMP nsWidget::SetFocus(void)
{
if (mBaseWindow) {
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::SetFocus() setting focus to 0x%lx\n", mBaseWindow));
mFocusWindow = mBaseWindow;
@ -384,6 +473,7 @@ void * nsWidget::GetNativeData(PRUint32 aDataType)
switch (aDataType) {
case NS_NATIVE_WIDGET:
case NS_NATIVE_WINDOW:
case NS_NATIVE_PLUGIN_PORT:
return (void *)mBaseWindow;
break;
case NS_NATIVE_DISPLAY:
@ -582,8 +672,12 @@ NS_IMETHODIMP nsWidget::SetCursor(nsCursor aCursor)
newCursor = XCreateFontCursor(mDisplay, XC_left_side);
break;
case eCursor_move:
newCursor = XCreateFontCursor(mDisplay, XC_dotbox);
break;
default:
NS_ASSERTION(PR_FALSE, "Invalid cursor type");
newCursor = XCreateFontCursor(mDisplay, XC_left_ptr);
break;
}
@ -630,32 +724,45 @@ void nsWidget::CreateNative(Window aParent, nsRect aRect)
attr.border_pixel = mBorderPixel;
// set the colormap
attr.colormap = xlib_rgb_get_cmap();
// FIXME: KenF
// attr.backing_store = Always;
// attr.save_under = True;
// attr.backing_planes = 0xFFFFFFFF; // 32 bit?
// attr.backing_pixel = 0xFFFFFFFF; // 32 bit.
// here's what's in the struct
attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel;
// attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel | CWBackingStore | CWSaveUnder | CWBackingPlanes | CWBackingPixel;
attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel ;
// check to see if there was actually a colormap.
if (attr.colormap)
attr_mask |= CWColormap;
CreateNativeWindow(aParent, mBounds, attr, attr_mask);
//CreateNativeWindow(aParent, aRect, attr, attr_mask);
CreateGC();
}
/* virtual */ long
nsWidget::GetEventMask()
{
long event_mask;
long event_mask;
event_mask =
ExposureMask |
ButtonPressMask |
ButtonReleaseMask |
PointerMotionMask |
VisibilityChangeMask |
event_mask =
ButtonMotionMask |
Button1MotionMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
ExposureMask |
KeyPressMask |
KeyReleaseMask |
StructureNotifyMask;
LeaveWindowMask |
PointerMotionMask |
StructureNotifyMask |
VisibilityChangeMask |
FocusChangeMask;
return event_mask;
return event_mask;
}
void nsWidget::CreateNativeWindow(Window aParent, nsRect aRect,
@ -691,6 +798,8 @@ void nsWidget::CreateNativeWindow(Window aParent, nsRect aRect,
height = aRect.height;
}
// make sure that we listen for events
mBaseWindow = XCreateWindow(mDisplay,
aParent,
aRect.x, aRect.y,
@ -701,6 +810,7 @@ void nsWidget::CreateNativeWindow(Window aParent, nsRect aRect,
mVisual, // visual
aMask,
&aAttr);
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG,
("nsWidget: Created window 0x%lx with parent 0x%lx %s\n",
mBaseWindow, aParent, (mIsToplevel ? "TopLevel" : "")));
@ -774,21 +884,10 @@ nsWidget::OnPaint(nsPaintEvent &event)
{
nsresult result = PR_FALSE;
if (mEventCallback) {
event.renderingContext = nsnull;
static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID);
static NS_DEFINE_IID(kRenderingContextIID, NS_IRENDERING_CONTEXT_IID);
if (NS_OK == nsComponentManager::CreateInstance(kRenderingContextCID,
nsnull,
kRenderingContextIID,
(void **)&event.renderingContext)) {
event.renderingContext->Init(mContext, this);
result = DispatchWindowEvent(event);
NS_RELEASE(event.renderingContext);
}
else {
result = PR_FALSE;
}
event.renderingContext = GetRenderingContext();
result = DispatchWindowEvent(event);
}
#ifdef TRACE_PAINT
static PRInt32 sPrintCount = 0;
@ -832,10 +931,23 @@ nsWidget::OnPaint(nsPaintEvent &event)
nsXUtils::XFlashWindow(mDisplay,mBaseWindow,1,100000,area);
#endif
}
return result;
}
// Added KenF FIXME
void nsWidget::OnDestroy()
{
mOnDestroyCalled = PR_TRUE;
nsBaseWidget::OnDestroy();
// M14/GTK creates a widget which is called kungFuDeathGrip
// and assigns it "this". This might be because its making sure that this
// widget isn't destroyed? (still has a reference to it?)
// Check into it. FIXME KenF
DispatchDestroyEvent();
}
PRBool nsWidget::OnDeleteWindow(void)
{
printf("nsWidget::OnDeleteWindow()\n");
@ -896,6 +1008,10 @@ PRBool nsWidget::DispatchMouseEvent(nsMouseEvent& aEvent)
PRBool
nsWidget::OnResize(nsSizeEvent &event)
{
mBounds.width = event.mWinWidth;
mBounds.height = event.mWinHeight;
nsresult result = PR_FALSE;
if (mEventCallback) {
result = DispatchWindowEvent(event);
@ -1029,7 +1145,10 @@ PRBool nsWidget::ConvertStatus(nsEventStatus aStatus)
void nsWidget::CreateGC(void)
{
// This is handled in nsDrawingSurfaceXlib, for now
#if 0
mGC = XCreateGC(mDisplay, mBaseWindow, 0, NULL);
#endif
}
void nsWidget::WidgetPut(nsWidget *aWidget)
@ -1040,74 +1159,32 @@ void nsWidget::WidgetPut(nsWidget *aWidget)
void nsWidget::WidgetMove(nsWidget *aWidget)
{
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetMove()\n"));
if (PR_TRUE == WidgetVisible(aWidget->mRequestedSize)) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Widget is visible...\n"));
XMoveWindow(aWidget->mDisplay, aWidget->mBaseWindow,
aWidget->mRequestedSize.x, aWidget->mRequestedSize.y);
if (aWidget->mIsShown == PR_TRUE) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Mapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Map();
}
}
else {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Widget is not visible...\n"));
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Unmapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Unmap();
}
XMoveWindow(aWidget->mDisplay, aWidget->mBaseWindow,
aWidget->mRequestedSize.x, aWidget->mRequestedSize.y);
}
void nsWidget::WidgetResize(nsWidget *aWidget)
{
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetResize()\n"));
// note that we do the resize before a map.
if (PR_TRUE == WidgetVisible(aWidget->mRequestedSize)) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Widget is visible...\n"));
XResizeWindow(aWidget->mDisplay, aWidget->mBaseWindow,
aWidget->mRequestedSize.width,
aWidget->mRequestedSize.height);
if (aWidget->mIsShown == PR_TRUE) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Mapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Map();
}
}
else {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Widget is not visible...\n"));
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Unmapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Unmap();
}
XResizeWindow(aWidget->mDisplay, aWidget->mBaseWindow,
aWidget->mRequestedSize.width,
aWidget->mRequestedSize.height);
}
void nsWidget::WidgetMoveResize(nsWidget *aWidget)
{
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetMoveResize()\n"));
if (PR_TRUE == WidgetVisible(aWidget->mRequestedSize)) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Widget is visible...\n"));
XResizeWindow(aWidget->mDisplay,
aWidget->mBaseWindow,
aWidget->mRequestedSize.width, aWidget->mRequestedSize.height);
XMoveWindow(aWidget->mDisplay, aWidget->mBaseWindow,
aWidget->mRequestedSize.x, aWidget->mRequestedSize.y);
if (aWidget->mIsShown == PR_TRUE) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Mapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Map();
}
}
else {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Widget is not visible...\n"));
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Unmapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Unmap();
}
XMoveResizeWindow(aWidget->mDisplay,
aWidget->mBaseWindow,
aWidget->mRequestedSize.x,
aWidget->mRequestedSize.y,
aWidget->mRequestedSize.width,
aWidget->mRequestedSize.height);
}
void nsWidget::WidgetShow(nsWidget *aWidget)
{
if (PR_TRUE == WidgetVisible(aWidget->mRequestedSize)) {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Mapping window 0x%lx...\n", aWidget->mBaseWindow));
aWidget->Map();
}
else {
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("Not Mapping window...\n"));
}
aWidget->Map();
}
PRBool nsWidget::WidgetVisible(nsRect &aBounds)
@ -1127,12 +1204,18 @@ PRBool nsWidget::WidgetVisible(nsRect &aBounds)
void nsWidget::Map(void)
{
XMapWindow(mDisplay, mBaseWindow);
if (!mMapped) {
XMapWindow(mDisplay, mBaseWindow);
mMapped = PR_TRUE;
}
}
void nsWidget::Unmap(void)
{
XUnmapWindow(mDisplay, mBaseWindow);
if (mMapped) {
XUnmapWindow(mDisplay, mBaseWindow);
mMapped = PR_FALSE;
}
}
void nsWidget::SetVisibility(int aState)

Просмотреть файл

@ -18,6 +18,8 @@
* Rights Reserved.
*
* Contributor(s):
* Ken Faulkner <faulkner@igelaus.com.au>
* Quy Tonthat <quy@igelaus.com.au>
*/
#ifndef nsWidget_h__
@ -30,7 +32,7 @@
#include "nsBaseWidget.h"
#include "nsHashtable.h"
#include "prlog.h"
#include "nsIRegion.h"
#include "nsIXlibWindowService.h"
#ifdef DEBUG_blizzard
@ -90,6 +92,8 @@ public:
virtual nsIFontMetrics* GetFont(void);
NS_IMETHOD SetFont(const nsFont &aFont);
NS_IMETHOD SetCursor(nsCursor aCursor);
void LockCursor(PRBool aLock);
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect & aRect, PRBool aIsSynchronous);
NS_IMETHOD Update();
@ -121,12 +125,16 @@ public:
virtual PRBool OnPaint(nsPaintEvent &event);
virtual PRBool OnResize(nsSizeEvent &event);
virtual PRBool OnDeleteWindow(void);
// KenF Added FIXME:
virtual void OnDestroy(void);
virtual PRBool DispatchMouseEvent(nsMouseEvent &aEvent);
virtual PRBool DispatchKeyEvent(nsKeyEvent &aKeyEvent);
virtual PRBool DispatchDestroyEvent(void);
static nsWidget * GetWidgetForWindow(Window aWindow);
void SetVisibility(int aState); // using the X constants here
void SetIonic(PRBool isIonic);
static Window GetFocusWindow(void);
PRBool DispatchWindowEvent(nsGUIEvent & aEvent);
@ -141,8 +149,13 @@ public:
static Atom WMSaveYourself;
static PRBool WMProtocolsInitialized;
// Checks if parent is alive. nsWidget has a stub, nsWindow has real
// thing. KenF
void *CheckParent(long ThisWindow);
protected:
nsCOMPtr<nsIRegion> mUpdateArea;
// private event functions
PRBool ConvertStatus(nsEventStatus aStatus);
@ -196,10 +209,13 @@ protected:
nsString mName; // name of the type of widget
PRBool mIsToplevel;
nsRect mRequestedSize;
PRBool mMapped;
static Window mFocusWindow;
private:
// Changed to protected so nsWindow has access to it. KenF
protected:
PRBool mListenForResizes; // If we're native we want to listen.
static nsHashtable * gsWindowList;
static nsXlibWindowCallback gsWindowCreateCallback;

Просмотреть файл

@ -18,205 +18,192 @@
* Rights Reserved.
*
* Contributor(s):
* Peter Hartshorn <peter@igelaus.com.au>
* Ken Faulkner <faulkner@igelaus.com.au>
*/
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
// includes for our specific widgets
#include "nsWindow.h"
#include "nsButton.h"
#include "nsCheckButton.h"
#include "nsComboBox.h"
#include "nsRadioButton.h"
#include "nsFileWidget.h"
#include "nsListBox.h"
#include "nsScrollBar.h"
#include "nsTextAreaWidget.h"
#include "nsTextWidget.h"
#include "nsAppShell.h"
#include "nsToolkit.h"
#include "nsLookAndFeel.h"
#include "nsLabel.h"
#include "nsTransferable.h"
#include "nsClipboard.h"
#include "nsXIFFormatConverter.h"
//#include "nsFontRetrieverService.h"
#include "nsDragService.h"
#include "nsFileSpecWithUIImpl.h"
#include "nsScrollBar.h"
#include "nsSound.h"
static NS_DEFINE_IID(kCWindow, NS_WINDOW_CID);
static NS_DEFINE_IID(kCChild, NS_CHILD_CID);
static NS_DEFINE_IID(kCButton, NS_BUTTON_CID);
static NS_DEFINE_IID(kCCheckButton, NS_CHECKBUTTON_CID);
static NS_DEFINE_IID(kCCombobox, NS_COMBOBOX_CID);
static NS_DEFINE_IID(kCFileOpen, NS_FILEWIDGET_CID);
static NS_DEFINE_IID(kCListbox, NS_LISTBOX_CID);
static NS_DEFINE_IID(kCRadioButton, NS_RADIOBUTTON_CID);
static NS_DEFINE_IID(kCHorzScrollbar, NS_HORZSCROLLBAR_CID);
static NS_DEFINE_IID(kCVertScrollbar, NS_VERTSCROLLBAR_CID);
static NS_DEFINE_IID(kCTextArea, NS_TEXTAREA_CID);
static NS_DEFINE_IID(kCTextField, NS_TEXTFIELD_CID);
static NS_DEFINE_IID(kCAppShell, NS_APPSHELL_CID);
static NS_DEFINE_IID(kCToolkit, NS_TOOLKIT_CID);
static NS_DEFINE_IID(kCLookAndFeel, NS_LOOKANDFEEL_CID);
static NS_DEFINE_IID(kCLabel, NS_LABEL_CID);
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(ChildWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsButton)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCheckButton)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFileWidget)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextWidget)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShell)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLabel)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXIFFormatConverter)
//NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontRetrieverService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFileSpecWithUIImpl)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
static NS_DEFINE_IID(kCImageButton, NS_IMAGEBUTTON_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
class nsWidgetFactory : public nsIFactory
{
public:
// nsISupports methods
NS_DECL_ISUPPORTS
// nsIFactory methods
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
nsWidgetFactory(const nsCID &aClass);
virtual ~nsWidgetFactory();
private:
nsCID mClassID;
};
NS_IMPL_ADDREF(nsWidgetFactory)
NS_IMPL_RELEASE(nsWidgetFactory)
nsWidgetFactory::nsWidgetFactory(const nsCID &aClass)
static nsresult nsHorizScrollbarConstructor (nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
NS_INIT_REFCNT();
mClassID = aClass;
}
nsWidgetFactory::~nsWidgetFactory()
{
}
nsresult nsWidgetFactory::QueryInterface(const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
// Always NULL result, in case of failure
*aResult = NULL;
if (aIID.Equals(kISupportsIID)) {
*aResult = (void *)(nsISupports*)this;
} else if (aIID.Equals(kIFactoryIID)) {
*aResult = (void *)(nsIFactory*)this;
}
if (*aResult == NULL) {
return NS_NOINTERFACE;
}
NS_ADDREF_THIS(); // Increase reference count for caller
return NS_OK;
}
nsresult nsWidgetFactory::CreateInstance(nsISupports* aOuter,
const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
if (nsnull != aOuter) {
return NS_ERROR_NO_AGGREGATION;
}
nsresult rv;
nsISupports *inst = nsnull;
if (mClassID.Equals(kCWindow)) {
inst = (nsISupports*)new nsWindow();
}
else if (mClassID.Equals(kCChild)) {
inst = (nsISupports*)new ChildWindow();
}
else if (mClassID.Equals(kCButton)) {
inst = (nsISupports*)(nsWindow*)new nsButton();
}
else if (mClassID.Equals(kCCheckButton)) {
inst = (nsISupports*)(nsWindow*)new nsCheckButton();
}
else if (mClassID.Equals(kCCombobox)) {
inst = (nsISupports*)(nsWindow*)new nsComboBox();
}
else if (mClassID.Equals(kCRadioButton)) {
inst = (nsISupports*)(nsWindow*)new nsRadioButton();
}
else if (mClassID.Equals(kCFileOpen)) {
inst = (nsISupports*)new nsFileWidget();
}
else if (mClassID.Equals(kCListbox)) {
inst = (nsISupports*)(nsWindow*)new nsListBox();
}
else if (mClassID.Equals(kCHorzScrollbar)) {
inst = (nsISupports*)(nsWindow*)new nsScrollbar(PR_FALSE);
}
else if (mClassID.Equals(kCVertScrollbar)) {
inst = (nsISupports*)(nsWindow*)new nsScrollbar(PR_TRUE);
}
else if (mClassID.Equals(kCTextArea)) {
inst = (nsISupports*)(nsWindow*)new nsTextAreaWidget();
}
else if (mClassID.Equals(kCTextField)) {
inst = (nsISupports*)(nsWindow*)new nsTextWidget();
}
else if (mClassID.Equals(kCAppShell)) {
inst = (nsISupports*)new nsAppShell();
}
else if (mClassID.Equals(kCToolkit)) {
inst = (nsISupports*)new nsToolkit();
}
else if (mClassID.Equals(kCLookAndFeel)) {
inst = (nsISupports*)new nsLookAndFeel();
}
else if (mClassID.Equals(kCLabel)) {
inst = (nsISupports*)(nsWindow*)new nsLabel();
}
if (inst == NULL) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = inst->QueryInterface(aIID, aResult);
if (res != NS_OK) {
// We didn't get the right interface, so clean up
delete inst;
}
return res;
}
nsresult nsWidgetFactory::LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
// return the proper factory to the caller
extern "C" NS_WIDGET nsresult
NSGetFactory(nsISupports* serviceMgr,
const nsCID &aClass,
const char *aClassName,
const char *aProgID,
nsIFactory **aFactory)
{
if (nsnull == aFactory) {
return NS_ERROR_NULL_POINTER;
if ( NULL == aResult )
{
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = NULL;
if (NULL != aOuter)
{
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
*aFactory = new nsWidgetFactory(aClass);
if (nsnull == aFactory) {
inst = (nsISupports *)(nsBaseWidget *)(nsWidget *)new nsScrollbar(PR_FALSE);
if (inst == NULL)
{
return NS_ERROR_OUT_OF_MEMORY;
}
return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory);
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
static nsresult nsVertScrollbarConstructor (nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsISupports *inst = nsnull;
if ( NULL == aResult )
{
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = NULL;
if (NULL != aOuter)
{
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
inst = (nsISupports *)(nsBaseWidget *)(nsWidget *)new nsScrollbar(PR_TRUE);
if (inst == NULL)
{
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
static nsModuleComponentInfo components[] =
{
{ "Xlib nsWindow",
NS_WINDOW_CID,
"mozilla.widgets.window.xlib.1",
nsWindowConstructor },
{ "Xlib Child nsWindow",
NS_CHILD_CID,
"mozilla.widgets.child_window.xlib.1",
ChildWindowConstructor },
{ "Xlib Button",
NS_BUTTON_CID,
"mozilla.widgets.button.xlib.1",
nsButtonConstructor },
{ "Xlib Check Button",
NS_CHECKBUTTON_CID,
"mozilla.widgets.checkbutton.xlib.1",
nsCheckButtonConstructor },
{ "Xlib File Widget",
NS_FILEWIDGET_CID,
"mozilla.widgets.filewidget.xlib.1",
nsFileWidgetConstructor },
{ "Xlib Horiz Scrollbar",
NS_HORZSCROLLBAR_CID,
"mozilla.widgets.horizscroll.xlib.1",
nsHorizScrollbarConstructor },
{ "Xlib Vert Scrollbar",
NS_VERTSCROLLBAR_CID,
"mozilla.widgets.vertscroll.xlib.1",
nsVertScrollbarConstructor },
{ "Xlib Text Widget",
NS_TEXTFIELD_CID,
"mozilla.widgets.textwidget.xlib.1",
nsTextWidgetConstructor },
{ "Xlib AppShell",
NS_APPSHELL_CID,
"mozilla.widget.appshell.xlib.1",
nsAppShellConstructor },
{ "Xlib Toolkit",
NS_TOOLKIT_CID,
"mozilla.widget.toolkit.xlib.1",
nsToolkitConstructor },
{ "Xlib Look And Feel",
NS_LOOKANDFEEL_CID,
"mozilla.widget.lookandfeel.xlib.1",
nsLookAndFeelConstructor },
{ "Xlib Label",
NS_LABEL_CID,
"mozilla.widget.label.xlib.1",
nsLabelConstructor },
{ "Xlib Sound",
NS_SOUND_CID,
"mozilla.widget.sound.xlib.1",
//"component://netscape/sound",
nsSoundConstructor },
{ "Transferrable",
NS_TRANSFERABLE_CID,
// "mozilla.widget.transferrable.xlib.1",
"component://netscape/widget/transferable",
nsTransferableConstructor },
{ "Xlib Clipboard",
NS_CLIPBOARD_CID,
// "mozilla.widget.clipboard.xlib.1",
"component://netscape/widget/clipboard",
nsClipboardConstructor },
{ "XIF Format Converter",
NS_XIFFORMATCONVERTER_CID,
"mozilla.widget.xifformatconverter.xlib.1",
nsXIFFormatConverterConstructor },
//{ "Xlib Font Retriever Service",
//NS_FONTRETRIEVERSERVICE_CID,
//"mozilla.widget.fontretrieverservice.xlib.1",
//nsFontRetrieverServiceConstructor },
{ "Xlib Drag Service",
NS_DRAGSERVICE_CID,
// "mozilla.widget.dragservice.xlib.1",
"component://netscape/widget/dragservice",
nsDragServiceConstructor },
{ "File Spec with UI",
NS_FILESPECWITHUI_CID,
// "mozilla.widget.filespecwithui.xlib.1",
"component://netscape/filespecwithui",
nsFileSpecWithUIImplConstructor }
};
NS_IMPL_NSGETMODULE("nsWidgetXLIBModule", components)

Просмотреть файл

@ -18,6 +18,8 @@
* Rights Reserved.
*
* Contributor(s):
* Peter Hartshorn <peter@igelaus.com.au>
* Ken Faulkner <faulkner@igelaus.com.au>
*/
#include "nsWindow.h"
@ -26,6 +28,141 @@
#include "nsFileSpec.h" // for nsAutoCString
#define ABS(i) ( i<0 ? 0-i : i )
// Routines implementing an update queue.
// We keep a single queue for all widgets because it is
// (most likely) more efficient and better looking to handle
// all the updates in one shot. Actually, this queue should
// be at most per-toplevel. FIXME.
//
nsListItem::nsListItem(void *aData, nsListItem *aPrev)
{
next = nsnull;
prev = aPrev;
data = aData;
}
nsList::nsList()
{
head = nsnull;
tail = nsnull;
}
nsList::~nsList()
{
reset();
}
void nsList::add(void *aData)
{
if (head == nsnull) { // We have an empty list, create the head
head = new nsListItem(aData, nsnull);
tail = head;
} else { // Append to the end of the list
tail->setNext(new nsListItem(aData, tail));
tail = tail->getNext(); // Reset the tail
tail->setNext(nsnull);
}
}
void nsList::remove(void *aData)
{
if (head == nsnull) { // Removing from a null list
return;
} else { // find the data
nsListItem *aItem = head;
while ((aItem != nsnull) && (aItem->getData() != aData)) {
aItem = aItem->getNext();
}
if (aItem == nsnull) { // we didn't find it
return;
} else
if (aItem == head) { // we have to remove the head
head = aItem->getNext();
delete aItem;
if (head == nsnull) // we have emptied the list
tail = nsnull;
else
head->setPrev(nsnull);
} else
if (aItem == tail) { // we have to remove the tail
tail = aItem->getPrev();
delete aItem;
if (tail == nsnull) // we have emptied the list
head = nsnull;
else
tail->setNext(nsnull);
} else { // we remove from the middle
nsListItem *prev = aItem->getPrev();
nsListItem *next = aItem->getNext();
delete aItem;
prev->setNext(next);
next->setPrev(prev);
}
}
}
void nsList::reset()
{
while (head != nsnull) {
void *aData = head->getData();
remove(aData);
}
}
static nsList *update_queue = nsnull;
void
nsWindow::UpdateIdle (void *data)
{
if (update_queue != nsnull) {
nsList *old_queue = update_queue;
nsListItem *tmp_list = old_queue->getHead();
update_queue = nsnull;
if (tmp_list != nsnull) {
while (tmp_list != nsnull)
{
nsWindow *window = (nsWindow *)tmp_list->getData();
window->Update();
window->mIsUpdating = PR_FALSE;
tmp_list = tmp_list->getNext();
}
}
delete old_queue;
}
}
void
nsWindow::QueueDraw ()
{
if (!mIsUpdating)
{
if (update_queue == nsnull)
update_queue = new nsList();
update_queue->add((void *)this);
mIsUpdating = PR_TRUE;
}
}
void
nsWindow::UnqueueDraw ()
{
if (mIsUpdating)
{
if (update_queue != nsnull)
update_queue->remove((void *)this);
mIsUpdating = PR_FALSE;
}
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
nsWindow::nsWindow() : nsWidget()
{
NS_INIT_REFCNT();
@ -34,23 +171,226 @@ nsWindow::nsWindow() : nsWidget()
mBackgroundPixel = xlib_rgb_xpixel_from_rgb(mBackground);
mBorderRGB = NS_RGB(255,255,255);
mBorderPixel = xlib_rgb_xpixel_from_rgb(mBorderRGB);
// FIXME KenF
mIsUpdating = PR_FALSE;
mBlockFocusEvents = PR_FALSE;
// FIXME New on M17 merge.
mWindowType = eWindowType_child;
mBorderStyle = eBorderStyle_default;
mIsToplevel = PR_FALSE;
}
nsWindow::~nsWindow()
{
// Should get called from ~nsWidget() anyway. KenF
// if (mBaseWindow)
//Destroy();
if (mIsUpdating)
UnqueueDraw();
}
void
nsWindow::DestroyNative(void)
PRBool nsWindow::OnExpose(nsPaintEvent &event)
{
nsresult result = PR_TRUE;
// call the event callback
if (mEventCallback)
{
event.renderingContext = nsnull;
// printf("nsWindow::OnExpose\n");
// expose.. we didn't get an Invalidate, so we should up the count here
// mBounds.UnionRect(mBounds, event.rect);
// SendExposeEvent();
}
return result;
}
NS_IMETHODIMP nsWindow::InvalidateRegion(const nsIRegion* aRegion, PRBool aIsSynchronous)
{
mUpdateArea->Union(*aRegion);
if (aIsSynchronous)
Update();
else
QueueDraw();
return NS_OK;
}
NS_IMETHODIMP nsWindow::SetFocus(void)
{
nsEventStatus status;
nsGUIEvent event;
// nsGUIEvent eventActivate;
if (mBaseWindow)
mFocusWindow = mBaseWindow;
if (mBlockFocusEvents)
return NS_OK;
mBlockFocusEvents = PR_TRUE;
event.message = NS_GOTFOCUS;
event.widget = this;
event.eventStructType = NS_GUI_EVENT;
event.time = 0;
event.point.x = 0;
event.point.y = 0;
AddRef();
DispatchEvent(&event, status);
Release();
event.message = NS_ACTIVATE;
event.widget = this;
event.eventStructType = NS_GUI_EVENT;
event.time = 0;
event.point.x = 0;
event.point.y = 0;
AddRef();
DispatchWindowEvent(event);
Release();
mBlockFocusEvents = PR_FALSE;
return NS_OK;
}
// Borrowed heavily from GTK. This should go through heirarchy of XWindow
// windows, and destroy the appropriate children.
// KenF
void
nsWindow::DestroyNativeChildren(void)
{
Display *display;
Window window;
Window root_return;
Window parent_return;
Window *children_return = NULL;
unsigned int nchildren_return = 0;
unsigned int i = 0;
display = mDisplay;
window = mBaseWindow;
XQueryTree(display, window, &root_return, &parent_return,
&children_return, &nchildren_return);
// walk the list of children
for (i=0; i < nchildren_return; i++)
{
Window child_window = children_return[i];
nsWindow *thisWindow = (nsWindow*) GetWidgetForWindow(child_window);
if (thisWindow)
{
thisWindow->Destroy();
}
}
// free up this struct
if (children_return)
XFree(children_return);
}
void nsWindow::DestroyNative(void)
{
// Destroy Children. DOH!!!! KenF
DestroyNativeChildren();
// This is handled in nsDrawingSurfaceXlib for now
#if 0
if (mGC)
XFreeGC(mDisplay, mGC);
#endif
if (mBaseWindow) {
XDestroyWindow(mDisplay, mBaseWindow);
DeleteWindowCallback(mBaseWindow);
XDestroyWindow(mDisplay, mBaseWindow);
DeleteWindowCallback(mBaseWindow);
}
}
/* NOTE: Originally, nsWindow just uses Resize from nsWidget.
* Changed so it will first use the nsWidget resizing routine, then
* send out a NS_SIZE event. This makes sure that the resizing is known
* by all parts that NEED to know about it.
* event bit is common for both resizes, yes, could make it a function,
* but haven't yet....
*/
NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint)
{
nsWidget::Resize(aWidth, aHeight, aRepaint);
nsSizeEvent sevent;
sevent.message = NS_SIZE;
sevent.widget = this;
sevent.eventStructType = NS_SIZE_EVENT;
sevent.windowSize = new nsRect (0, 0, aWidth, aHeight);
sevent.point.x = 0;
sevent.point.y = 0;
sevent.mWinWidth = aWidth;
sevent.mWinHeight = aHeight;
sevent.time = 0;
AddRef();
OnResize(sevent);
Release();
delete sevent.windowSize;
return NS_OK;
}
/* NOTE: Originally, nsWindow just uses Resize from nsWidget.
* Changed so it will first use the nsWidget resizing routine, then
* send out a NS_SIZE event. This makes sure that the resizing is known
* by all parts that NEED to know about it.
*/
NS_IMETHODIMP nsWindow::Resize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint)
{
nsWidget::Resize(aX, aY, aWidth, aHeight, aRepaint);
nsSizeEvent sevent;
sevent.message = NS_SIZE;
sevent.widget = this;
sevent.eventStructType = NS_SIZE_EVENT;
sevent.windowSize = new nsRect (0, 0, aWidth, aHeight);
sevent.point.x = 0;
sevent.point.y = 0;
sevent.mWinWidth = aWidth;
sevent.mWinHeight = aHeight;
sevent.time = 0;
AddRef();
OnResize(sevent);
Release();
delete sevent.windowSize;
return NS_OK;
}
#if 0
void nsWindow::CreateNative(Window aParent, nsRect aRect)
{
@ -102,7 +442,8 @@ nsWindow::GetEventMask()
LeaveWindowMask |
PointerMotionMask |
StructureNotifyMask |
VisibilityChangeMask;
VisibilityChangeMask |
FocusChangeMask;
return event_mask;
}
@ -114,79 +455,102 @@ static PRInt32 sInvalidatePrintCount = 0;
NS_IMETHODIMP nsWindow::Invalidate(PRBool aIsSynchronous)
{
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWindow::Invalidate(sync)\n"));
nsPaintEvent pevent;
pevent.message = NS_PAINT;
pevent.widget = this;
pevent.eventStructType = NS_PAINT_EVENT;
pevent.rect = new nsRect (mBounds.x, mBounds.y,
mBounds.width, mBounds.height);
pevent.time = PR_Now();
mUpdateArea->SetTo(mBounds.x, mBounds.y, mBounds.width, mBounds.height);
if (aIsSynchronous)
Update();
else
QueueDraw();
#ifdef TRACE_INVALIDATE
printf("%4d nsWindow::Invalidate(this=%p,name=%s,xid=%p,sync=%s)\n",
sInvalidatePrintCount++,
(void *) this,
(const char *) nsCAutoString(mName),
(void *) mBaseWindow,
aIsSynchronous ? "yes" : "no");
#endif
AddRef();
OnPaint(pevent);
Release();
delete pevent.rect;
return NS_OK;
}
NS_IMETHODIMP nsWindow::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
{
PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWindow::Invalidate(rect, sync)\n"));
nsPaintEvent pevent;
pevent.message = NS_PAINT;
pevent.widget = this;
pevent.eventStructType = NS_PAINT_EVENT;
pevent.rect = new nsRect(aRect);
pevent.time = PR_Now();
#ifdef TRACE_INVALIDATE
printf("%4d nsWidget::Invalidate(this=%p,name=%s,xid=%p,sync=%s,rect=%d,%d,%d,%d)\n",
sInvalidatePrintCount++,
(void *) this,
(const char *) nsCAutoString(mName),
(void *) mBaseWindow,
aIsSynchronous ? "yes" : "no",
aRect.x,
aRect.y,
aRect.width,
aRect.height);
#endif
AddRef();
OnPaint(pevent);
Release();
// XXX will this leak?
delete pevent.rect;
mUpdateArea->Union(aRect.x, aRect.y, aRect.width, aRect.height);
if (aIsSynchronous)
Update();
else
QueueDraw();
return NS_OK;
}
NS_IMETHODIMP nsWindow::Update()
{
//PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWindow::Update()\n"));
if (mIsUpdating)
UnqueueDraw();
nsPaintEvent pevent;
pevent.message = NS_PAINT;
pevent.widget = this;
pevent.eventStructType = NS_PAINT_EVENT;
pevent.rect = new nsRect (mBounds.x, mBounds.y,
mBounds.width, mBounds.height);
pevent.time = PR_Now();
AddRef();
OnPaint(pevent);
Release();
pevent.rect = new nsRect (0,0,0,0);
pevent.time = 0;
pevent.region = mUpdateArea;
if (!mUpdateArea->IsEmpty()) {
PRUint32 numRects;
mUpdateArea->GetNumRects(&numRects);
if (numRects != 1 && numRects < 10) {
nsRegionRectSet *regionRectSet = nsnull;
if (NS_FAILED(mUpdateArea->GetRects(&regionRectSet)))
return NS_ERROR_FAILURE;
PRUint32 len;
PRUint32 i;
len = regionRectSet->mRectsLen;
for (i=0; i<len; ++i) {
nsRegionRect *r = &(regionRectSet->mRects[i]);
pevent.widget = this;
pevent.rect->SetRect(r->x, r->y, r->width, r->height);
pevent.time = PR_Now();
AddRef();
OnPaint(pevent);
Release();
}
mUpdateArea->FreeRects(regionRectSet);
mUpdateArea->SetTo(0,0,0,0);
return NS_OK;
} else {
PRInt32 x,y,w,h;
mUpdateArea->GetBoundingBox(&x,&y,&w,&h);
pevent.widget = this;
pevent.rect->SetRect(x,y,w,h);
AddRef();
OnPaint(pevent);
Release();
mUpdateArea->SetTo(0,0,0,0);
}
}
delete pevent.rect;
// The view manager also expects us to force our
// children to update too!
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
if (children)
{
children->First();
do
{
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*,child);
NS_RELEASE(child);
childWindow->Update();
}
} while (NS_SUCCEEDED(children->Next()));
}
return NS_OK;
}
@ -194,6 +558,63 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
{
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWindow::Scroll()\n"));
if (mIsUpdating)
UnqueueDraw();
PRInt32 srcX, srcY, destX, destY, width, height;
nsRect aRect;
GC gc;
gc = XCreateGC(mDisplay, mBaseWindow, 0, NULL);
if (aDx < 0 || aDy < 0)
{
srcX = mBounds.x + ABS(aDx);
srcY = mBounds.y + ABS(aDy);
destX = mBounds.x;
destY = mBounds.y;
width = mBounds.width - ABS(aDx);
height = mBounds.height - ABS(aDy);
} else
if (aDx > 0 || aDy > 0)
{
srcX = mBounds.x;
srcY = mBounds.y;
destX = mBounds.x + ABS(aDx);
destY = mBounds.y + ABS(aDy);
width = mBounds.width - ABS(aDx);
height = mBounds.height - ABS(aDy);
}
XCopyArea(mDisplay, mBaseWindow, mBaseWindow, gc,
srcX, srcY, width, height, destX, destY);
XFreeGC(mDisplay, gc);
width = mBounds.width;
height = mBounds.height;
if (aDx != 0 || aDy != 0) {
if (aDx < 0) {
aRect.SetRect(width + aDx, 0,
-aDx, height);
}
else if (aDx > 0) {
aRect.SetRect(0,0, aDx, height);
}
if (aDy < 0) {
aRect.SetRect(0, height + aDy,
width, -aDy);
}
else if (aDy > 0) {
aRect.SetRect(0,0, width, aDy);
}
mUpdateArea->Offset(aDx, aDy);
Invalidate(aRect, PR_TRUE);
}
//--------
// Scroll the children
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
@ -205,26 +626,56 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWidget* childWindow = NS_STATIC_CAST(nsWidget*,child);
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*,child);
NS_RELEASE(child);
nsRect bounds;
childWindow->GetRequestedBounds(bounds);
bounds.x += aDx;
bounds.y += aDy;
PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWindow::Scroll moving child to %d, %d\n", bounds.x, bounds.y));
childWindow->Move(bounds.x, bounds.y);
childWindow->Move(bounds.x + aDx, bounds.y + aDy);
Invalidate(bounds, PR_TRUE);
}
} while (NS_SUCCEEDED(children->Next()));
} while (NS_SUCCEEDED(children->Next()));
}
if (aClipRect)
Invalidate(*aClipRect, PR_TRUE);
else
Invalidate(PR_TRUE);
// If we are obscurred by another window we have to update those areas
// which were not copied with the XCopyArea function.
if (mVisibility == VisibilityPartiallyObscured)
{
XEvent event;
PRBool needToUpdate = PR_FALSE;
mUpdateArea->SetTo(0,0,0,0);
while(XCheckWindowEvent(mDisplay, mBaseWindow, 0xffffffff, &event))
{
if (event.type == GraphicsExpose) {
nsRect rect;
rect.SetRect(event.xgraphicsexpose.x,
event.xgraphicsexpose.y,
event.xgraphicsexpose.width,
event.xgraphicsexpose.height);
mUpdateArea->Union(rect.x, rect.y, rect.width, rect.height);
needToUpdate = PR_TRUE;
if (event.xgraphicsexpose.count == 0) {
continue;
}
}
}
if (needToUpdate == PR_TRUE)
Update();
}
return NS_OK;
}
NS_IMETHODIMP nsWindow::ScrollWidgets(PRInt32 aDx, PRInt32 aDy)
{
return Scroll(aDx, aDy, nsnull);
}
NS_IMETHODIMP nsWindow::ScrollRect(nsRect &aSrcRect, PRInt32 aDx, PRInt32 aDy)
{
return Scroll(aDx, aDy, nsnull);
}
NS_IMETHODIMP nsWindow::SetTitle(const nsString& aTitle)
{
if(!mBaseWindow)

Просмотреть файл

@ -18,6 +18,8 @@
* Rights Reserved.
*
* Contributor(s):
* Peter Hartshorn <peter@igelaus.com.au>
* Ken Faulkner <faulkner@igelaus.com.au>
*/
#ifndef nsWindow_h__
@ -27,21 +29,83 @@
#include "nsString.h"
class nsListItem {
public:
nsListItem() {}
nsListItem(void *aData, nsListItem *aPrev);
~nsListItem() {}
void *getData() { return data; }
nsListItem *getNext() { return next; }
void setNext(nsListItem *aNext) { next = aNext; }
nsListItem *getPrev() { return prev; };
void setPrev(nsListItem *aPrev) { prev = aPrev; }
private:
void *data;
nsListItem *next;
nsListItem *prev;
};
class nsList {
public:
nsList();
~nsList();
nsListItem *getHead() { return head; }
void add(void *aData);
void remove(void *aData);
void reset();
private:
nsListItem *head;
nsListItem *tail;
};
class nsWindow : public nsWidget
{
public:
nsWindow();
~nsWindow();
static void UpdateIdle (void *data);
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect & aRect, PRBool aIsSynchronous);
NS_IMETHOD InvalidateRegion(const nsIRegion* aRegion, PRBool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect);
NS_IMETHOD ScrollWidgets(PRInt32 aDx, PRInt32 aDy);
NS_IMETHOD ScrollRect(nsRect &aSrcRect, PRInt32 aDx, PRInt32 aDy);
NS_IMETHOD SetTitle(const nsString& aTitle);
NS_IMETHOD Resize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD SetFocus(void);
virtual PRBool OnExpose(nsPaintEvent &event);
protected:
virtual void DestroyNative(void);
virtual void DestroyNativeChildren(void);
virtual long GetEventMask();
void QueueDraw();
void UnqueueDraw();
PRBool mIsUpdating;
PRBool mBlockFocusEvents;
#if 0
virtual void CreateNative(Window aParent, nsRect aRect);
#endif

Просмотреть файл

@ -19,6 +19,7 @@
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Peter Hartshorn <peter@igelaus.com.au>
*/
#include "nsIXlibWindowService.h"
@ -60,7 +61,7 @@ nsXlibWindowServiceFactory::~nsXlibWindowServiceFactory()
{
}
NS_IMPL_ISUPPORTS(nsXlibWindowServiceFactory, NS_GET_IID(nsIFactory))
NS_IMPL_THREADSAFE_ISUPPORTS(nsXlibWindowServiceFactory, NS_GET_IID(nsIFactory))
NS_IMETHODIMP
nsXlibWindowServiceFactory::CreateInstance(nsISupports *aOuter,