зеркало из https://github.com/mozilla/gecko-dev.git
Updating xlib. Not part of the build
This commit is contained in:
Родитель
0a13534f94
Коммит
2020b8cdf8
|
@ -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(¤tlyDragging);
|
||||
}
|
||||
}
|
||||
|
||||
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(¤tlyDragging);
|
||||
}
|
||||
}
|
||||
|
||||
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(¤tlyDragging);
|
||||
}
|
||||
}
|
||||
|
||||
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(¤tlyDragging);
|
||||
}
|
||||
}
|
||||
|
||||
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(®ionRectSet)))
|
||||
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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче