* moved input handling code from Desktop class to RootLayer
* PollerThread was replaced by WorkingThread(RootLayerX) thread which is created every time a RootLayer object is created and destroyed when deleted. * ViewDriver now initializes the "inputServer" port because it is one of the first objects instantiated by the server. * changed the way a RootLayer(ex Poller) quits. The thread is not killed anymore, it is been asked to quit nicely. This prevents (future) deadlocks. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10780 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -90,12 +90,10 @@ AppServer::AppServer(void) : BApplication (SERVER_SIGNATURE)
|
||||
AppServer::AppServer(void)
|
||||
#endif
|
||||
{
|
||||
fMousePort= create_port(200,SERVER_INPUT_PORT);
|
||||
fMessagePort= create_port(200,SERVER_PORT_NAME);
|
||||
|
||||
fAppList= new BList(0);
|
||||
fQuittingServer= false;
|
||||
fExitPoller= false;
|
||||
make_decorator= NULL;
|
||||
|
||||
// We need this in order for new_decorator to be able to instantiate new decorators
|
||||
@@ -153,11 +151,6 @@ AppServer::AppServer(void)
|
||||
// This locker is to mediate access to the make_decorator pointer
|
||||
fDecoratorLock= create_sem(1,"app_server_decor_sem");
|
||||
|
||||
// Spawn our input-polling thread
|
||||
fPollerThreadID= spawn_thread(PollerThread, "Poller", B_NORMAL_PRIORITY, this);
|
||||
if (fPollerThreadID >= 0)
|
||||
resume_thread(fPollerThreadID);
|
||||
|
||||
// Spawn our thread-monitoring thread
|
||||
fPicassoThreadID= spawn_thread(PicassoThread,"Picasso", B_NORMAL_PRIORITY, this);
|
||||
if (fPicassoThreadID >= 0)
|
||||
@@ -195,7 +188,6 @@ AppServer::~AppServer(void)
|
||||
// If these threads are still running, kill them - after this, if exit_poller
|
||||
// is deleted, who knows what will happen... These things will just return an
|
||||
// error and fail if the threads have already exited.
|
||||
kill_thread(fPollerThreadID);
|
||||
kill_thread(fPicassoThreadID);
|
||||
|
||||
delete fontserver;
|
||||
@@ -203,61 +195,6 @@ AppServer::~AppServer(void)
|
||||
make_decorator=NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Thread function for polling and handling input messages
|
||||
\param data Pointer to the app_server to which the thread belongs
|
||||
\return Throwaway value - always 0
|
||||
*/
|
||||
int32 AppServer::PollerThread(void *data)
|
||||
{
|
||||
// This thread handles nothing but input messages for mouse and keyboard
|
||||
AppServer *appserver=(AppServer*)data;
|
||||
BPortLink mousequeue(-1,appserver->fMousePort);
|
||||
int32 code=0;
|
||||
status_t err=B_OK;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
STRACE(("info: AppServer::PollerThread listening on port %ld.\n", appserver->fMousePort));
|
||||
err=mousequeue.GetNextReply(&code);
|
||||
|
||||
if(err<B_OK)
|
||||
{
|
||||
STRACE(("PollerThread:mousequeue.GetNextReply failed\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(code)
|
||||
{
|
||||
// We don't need to do anything with these two, so just pass them
|
||||
// onto the active application. Eventually, we will end up passing
|
||||
// them onto the window which is currently under the cursor.
|
||||
case B_MOUSE_DOWN:
|
||||
case B_MOUSE_UP:
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
case B_MOUSE_MOVED:
|
||||
desktop->MouseEventHandler(code,mousequeue);
|
||||
break;
|
||||
|
||||
case B_KEY_DOWN:
|
||||
case B_KEY_UP:
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
case B_MODIFIERS_CHANGED:
|
||||
desktop->KeyboardEventHandler(code,mousequeue);
|
||||
break;
|
||||
|
||||
default:
|
||||
STRACE(("AppServer::Poller received unexpected code %lx\n",code));
|
||||
break;
|
||||
}
|
||||
|
||||
if(appserver->fExitPoller)
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Thread function for watching for dead apps
|
||||
\param data Pointer to the app_server to which the thread belongs
|
||||
@@ -270,24 +207,17 @@ int32 AppServer::PicassoThread(void *data)
|
||||
ServerApp *app;
|
||||
for(;;)
|
||||
{
|
||||
i = 0;
|
||||
acquire_sem(appserver->fAppListLock);
|
||||
for(i= 0; i < appserver->fAppList->CountItems(); i++)
|
||||
for(;;)
|
||||
{
|
||||
app=(ServerApp*)appserver->fAppList->ItemAt(i);
|
||||
app=(ServerApp*)appserver->fAppList->ItemAt(i++);
|
||||
if(!app)
|
||||
{
|
||||
printf("PANIC: NULL app in app list\n");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
app->PingTarget();
|
||||
}
|
||||
release_sem(appserver->fAppListLock);
|
||||
|
||||
// if poller thread has to exit, so do we - I just was too lazy
|
||||
// to rename the variable name. ;)
|
||||
if(appserver->fExitPoller)
|
||||
break;
|
||||
|
||||
release_sem(appserver->fAppListLock);
|
||||
// we do this every other second so as not to suck *too* many CPU cycles
|
||||
snooze(2000000);
|
||||
}
|
||||
@@ -746,14 +676,6 @@ void AppServer::DispatchMessage(int32 code, BPortLink &msg)
|
||||
|
||||
// When we delete the last ServerApp, we can exit the server
|
||||
fQuittingServer=true;
|
||||
fExitPoller=true;
|
||||
|
||||
// also wait for picasso thread
|
||||
kill_thread(fPicassoThreadID);
|
||||
|
||||
// poller thread is stuck reading messages from its input port
|
||||
// so, there is no cleaner way to make it quit, other than killing it!
|
||||
kill_thread(fPollerThreadID);
|
||||
|
||||
// we are now clear to exit
|
||||
break;
|
||||
|
||||
@@ -56,19 +56,16 @@ private:
|
||||
// global function pointer
|
||||
create_decorator *make_decorator;
|
||||
|
||||
port_id fMessagePort,
|
||||
fMousePort;
|
||||
port_id fMessagePort;
|
||||
|
||||
image_id fDecoratorID;
|
||||
|
||||
BString fDecoratorName;
|
||||
|
||||
bool fQuittingServer,
|
||||
fExitPoller;
|
||||
bool fQuittingServer;
|
||||
|
||||
BList *fAppList;
|
||||
thread_id fPollerThreadID,
|
||||
fPicassoThreadID;
|
||||
thread_id fPicassoThreadID;
|
||||
|
||||
sem_id fActiveAppLock,
|
||||
fAppListLock,
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Desktop.cpp
|
||||
// Author: Adi Oanca <adioanca@mymail.ro>
|
||||
// Author: Adi Oanca <adioanca@cotty.iren.ro>
|
||||
// Description: Class used to encapsulate desktop management
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <Entry.h>
|
||||
#include <Region.h>
|
||||
#include <Message.h>
|
||||
|
||||
@@ -45,7 +44,6 @@
|
||||
#include "Workspace.h"
|
||||
|
||||
//#define DEBUG_DESKTOP
|
||||
#define DEBUG_KEYHANDLING
|
||||
|
||||
#ifdef DEBUG_DESKTOP
|
||||
#define STRACE(a) printf(a)
|
||||
@@ -55,27 +53,23 @@
|
||||
|
||||
Desktop::Desktop(void)
|
||||
{
|
||||
fDragMessage = NULL;
|
||||
fActiveRootLayer = NULL;
|
||||
fMouseTarget = NULL;
|
||||
fActiveScreen = NULL;
|
||||
fScreenShotIndex = 1;
|
||||
}
|
||||
|
||||
Desktop::~Desktop(void)
|
||||
{
|
||||
if (fDragMessage)
|
||||
delete fDragMessage;
|
||||
|
||||
void *ptr;
|
||||
|
||||
for(int32 i=0; (ptr=fWinBorderList.ItemAt(i)); i++)
|
||||
delete (WinBorder*)ptr;
|
||||
|
||||
for(int32 i=0; (ptr=fRootLayerList.ItemAt(i)); i++)
|
||||
delete (RootLayer*)ptr;
|
||||
|
||||
for(int32 i=0; (ptr=fScreenList.ItemAt(i)); i++)
|
||||
delete (Screen*)ptr;
|
||||
|
||||
for(int32 i=0; (ptr=fWinBorderList.ItemAt(i)); i++)
|
||||
delete (WinBorder*)ptr;
|
||||
}
|
||||
|
||||
void Desktop::Init(void)
|
||||
@@ -245,7 +239,7 @@ void Desktop::AddWinBorder(WinBorder* winBorder)
|
||||
return;
|
||||
|
||||
// special case for Tracker background window.
|
||||
if (winBorder->fLevel == B_SYSTEM_LAST)
|
||||
if (winBorder->Level() == B_SYSTEM_LAST)
|
||||
{
|
||||
// it's added in all RottLayers
|
||||
for(int32 i=0; i<fRootLayerList.CountItems(); i++)
|
||||
@@ -267,7 +261,7 @@ void Desktop::RemoveWinBorder(WinBorder* winBorder)
|
||||
{
|
||||
desktop->fGeneralLock.Lock();
|
||||
|
||||
if(winBorder->fLevel == B_SYSTEM_LAST)
|
||||
if(winBorder->Level() == B_SYSTEM_LAST)
|
||||
{
|
||||
for(int32 i=0; i<fRootLayerList.CountItems(); i++)
|
||||
((RootLayer*)fRootLayerList.ItemAt(i))->RemoveWinBorder(winBorder);
|
||||
@@ -287,603 +281,6 @@ bool Desktop::HasWinBorder(WinBorder* winBorder)
|
||||
return fWinBorderList.HasItem(winBorder);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Input related methods
|
||||
//---------------------------------------------------------------------------
|
||||
void Desktop::MouseEventHandler(int32 code, BPortLink& msg)
|
||||
{
|
||||
// TODO: locking mechanism needs SERIOUS rethought
|
||||
switch(code)
|
||||
{
|
||||
case B_MOUSE_DOWN:
|
||||
{
|
||||
// Attached data:
|
||||
// 1) int64 - time of mouse click
|
||||
// 2) float - x coordinate of mouse click
|
||||
// 3) float - y coordinate of mouse click
|
||||
// 4) int32 - modifier keys down
|
||||
// 5) int32 - buttons down
|
||||
// 6) int32 - clicks
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_DOWN;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.where.x);
|
||||
msg.Read<float>(&evt.where.y);
|
||||
msg.Read<int32>(&evt.modifiers);
|
||||
msg.Read<int32>(&evt.buttons);
|
||||
msg.Read<int32>(&evt.clicks);
|
||||
|
||||
// printf("MOUSE DOWN: at (%f, %f)\n", evt.where.x, evt.where.y);
|
||||
|
||||
WinBorder *target=NULL;
|
||||
RootLayer *rl=NULL;
|
||||
Workspace *ws=NULL;
|
||||
rl = ActiveRootLayer();
|
||||
ws = rl->ActiveWorkspace();
|
||||
target = rl->WinBorderAt(evt.where);
|
||||
if (target)
|
||||
{
|
||||
fGeneralLock.Lock();
|
||||
rl->fMainLock.Lock();
|
||||
|
||||
STRACE(("Target: %s\n", target->GetName()));
|
||||
STRACE(("Front: %s\n", ws->FrontLayer()->GetName()));
|
||||
STRACE(("Focus: %s\n", ws->FocusLayer()->GetName()));
|
||||
|
||||
WinBorder *previousFocus=NULL;
|
||||
WinBorder *activeFocus=NULL;
|
||||
BRegion invalidRegion;
|
||||
|
||||
BMessage downmsg(B_MOUSE_DOWN);
|
||||
downmsg.AddInt64("when",evt.when);
|
||||
downmsg.AddPoint("where",evt.where);
|
||||
downmsg.AddInt32("modifiers",evt.modifiers);
|
||||
downmsg.AddInt32("buttons",evt.buttons);
|
||||
downmsg.AddInt32("clicks",evt.clicks);
|
||||
|
||||
if (target!=ws->FrontLayer())
|
||||
{
|
||||
ws->BringToFrontANormalWindow(target);
|
||||
ws->SearchAndSetNewFront(target);
|
||||
previousFocus = ws->FocusLayer();
|
||||
ws->SearchAndSetNewFocus(target);
|
||||
activeFocus = ws->FocusLayer();
|
||||
|
||||
activeFocus->Window()->Lock();
|
||||
|
||||
if (target == activeFocus && target->Window()->Flags() & B_WILL_ACCEPT_FIRST_CLICK)
|
||||
target->MouseDown(evt, true);
|
||||
else
|
||||
target->MouseDown(evt, false);
|
||||
|
||||
// may or may not be empty.
|
||||
|
||||
// TODO: B_MOUSE_DOWN: what if modal of floating windows are in front of us?
|
||||
invalidRegion.Include(&(activeFocus->fFull));
|
||||
invalidRegion.Include(&(activeFocus->fTopLayer->fFull));
|
||||
activeFocus->fParent->RebuildAndForceRedraw(invalidRegion, activeFocus);
|
||||
|
||||
if (previousFocus != activeFocus && previousFocus)
|
||||
{
|
||||
if (previousFocus->fVisible.CountRects() > 0)
|
||||
{
|
||||
invalidRegion.MakeEmpty();
|
||||
invalidRegion.Include(&(previousFocus->fVisible));
|
||||
activeFocus->fParent->Invalidate(invalidRegion);
|
||||
}
|
||||
}
|
||||
|
||||
fMouseTarget = target;
|
||||
|
||||
STRACE(("2Target: %s\n", target->GetName()));
|
||||
STRACE(("2Front: %s\n", ws->FrontLayer()->GetName()));
|
||||
STRACE(("2Focus: %s\n", ws->FocusLayer()->GetName()));
|
||||
|
||||
fMouseTarget->Window()->SendMessageToClient(&downmsg);
|
||||
activeFocus->Window()->Unlock();
|
||||
}
|
||||
else // target == ws->FrontLayer()
|
||||
{
|
||||
// only if target has the focus!
|
||||
if (target == ws->FocusLayer())
|
||||
{
|
||||
target->Window()->Lock();
|
||||
target->MouseDown(evt, true);
|
||||
target->Window()->SendMessageToClient(&downmsg);
|
||||
target->Window()->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
previousFocus = ws->FocusLayer();
|
||||
ws->SearchAndSetNewFocus(target);
|
||||
activeFocus = ws->FocusLayer();
|
||||
|
||||
activeFocus->Window()->Lock();
|
||||
|
||||
if (target == activeFocus && target->Window()->Flags() & B_WILL_ACCEPT_FIRST_CLICK)
|
||||
target->MouseDown(evt, true);
|
||||
else
|
||||
target->MouseDown(evt, false);
|
||||
|
||||
// may or may not be empty.
|
||||
|
||||
// TODO: B_MOUSE_DOWN: what if modal of floating windows are in front of us?
|
||||
invalidRegion.Include(&(activeFocus->fFull));
|
||||
invalidRegion.Include(&(activeFocus->fTopLayer->fFull));
|
||||
activeFocus->fParent->RebuildAndForceRedraw(invalidRegion, activeFocus);
|
||||
|
||||
if (previousFocus != activeFocus && previousFocus)
|
||||
{
|
||||
if (previousFocus->fVisible.CountRects() > 0)
|
||||
{
|
||||
invalidRegion.MakeEmpty();
|
||||
invalidRegion.Include(&(previousFocus->fVisible));
|
||||
activeFocus->fParent->Invalidate(invalidRegion);
|
||||
}
|
||||
}
|
||||
fMouseTarget = target;
|
||||
fMouseTarget->Window()->SendMessageToClient(&downmsg);
|
||||
|
||||
activeFocus->Window()->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
rl->fMainLock.Unlock();
|
||||
fGeneralLock.Unlock();
|
||||
}
|
||||
else // target == NULL
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
case B_MOUSE_UP:
|
||||
{
|
||||
// Attached data:
|
||||
// 1) int64 - time of mouse click
|
||||
// 2) float - x coordinate of mouse click
|
||||
// 3) float - y coordinate of mouse click
|
||||
// 4) int32 - modifier keys down
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_UP;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.where.x);
|
||||
msg.Read<float>(&evt.where.y);
|
||||
msg.Read<int32>(&evt.modifiers);
|
||||
|
||||
if (!fMouseTarget)
|
||||
{
|
||||
WinBorder *target = ActiveRootLayer()->WinBorderAt(BPoint(evt.where.x, evt.where.y));
|
||||
if(!target)
|
||||
break;
|
||||
fMouseTarget=target;
|
||||
}
|
||||
|
||||
fMouseTarget->Window()->Lock();
|
||||
fMouseTarget->MouseUp(evt);
|
||||
|
||||
BMessage upmsg(B_MOUSE_UP);
|
||||
upmsg.AddInt64("when",evt.when);
|
||||
upmsg.AddPoint("where",evt.where);
|
||||
upmsg.AddInt32("modifiers",evt.modifiers);
|
||||
|
||||
fMouseTarget->Window()->SendMessageToClient(&upmsg);
|
||||
fMouseTarget->Window()->Unlock();
|
||||
|
||||
STRACE(("MOUSE UP: at (%f, %f)\n", evt.where.x, evt.where.y));
|
||||
|
||||
break;
|
||||
}
|
||||
case B_MOUSE_MOVED:
|
||||
{
|
||||
// Attached data:
|
||||
// 1) int64 - time of mouse click
|
||||
// 2) float - x coordinate of mouse click
|
||||
// 3) float - y coordinate of mouse click
|
||||
// 4) int32 - buttons down
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_MOVED;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.where.x);
|
||||
msg.Read<float>(&evt.where.y);
|
||||
msg.Read<int32>(&evt.buttons);
|
||||
|
||||
fActiveScreen->DDriver()->MoveCursorTo(evt.where.x, evt.where.y);
|
||||
|
||||
if (!fMouseTarget)
|
||||
{
|
||||
WinBorder *target = ActiveRootLayer()->WinBorderAt(BPoint(evt.where.x, evt.where.y));
|
||||
if(!target)
|
||||
break;
|
||||
fMouseTarget=target;
|
||||
}
|
||||
|
||||
fMouseTarget->Window()->Lock();
|
||||
fMouseTarget->MouseMoved(evt);
|
||||
|
||||
BMessage movemsg(B_MOUSE_MOVED);
|
||||
movemsg.AddInt64("when",evt.when);
|
||||
movemsg.AddPoint("where",evt.where);
|
||||
movemsg.AddInt32("buttons",evt.buttons);
|
||||
|
||||
fMouseTarget->Window()->SendMessageToClient(&movemsg);
|
||||
fMouseTarget->Window()->Unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
{
|
||||
// FEATURE: This is a tentative change: mouse wheel messages are always sent to the window
|
||||
// under the cursor. It's pretty stupid to send it to the active window unless a particular
|
||||
// view has locked focus via SetMouseEventMask
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_WHEEL_CHANGED;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.wheel_delta_x);
|
||||
msg.Read<float>(&evt.wheel_delta_y);
|
||||
|
||||
BMessage wheelmsg(B_MOUSE_WHEEL_CHANGED);
|
||||
wheelmsg.AddInt64("when",evt.when);
|
||||
wheelmsg.AddFloat("be:wheel_delta_x",evt.wheel_delta_x);
|
||||
wheelmsg.AddFloat("be:wheel_delta_y",evt.wheel_delta_y);
|
||||
|
||||
if(!fMouseTarget)
|
||||
{
|
||||
fMouseTarget = ActiveRootLayer()->WinBorderAt(GetDisplayDriver()->GetCursorPosition());
|
||||
|
||||
// We do nothing because there ain't a window to receive the message
|
||||
if(!fMouseTarget)
|
||||
break;
|
||||
}
|
||||
|
||||
fMouseTarget->Window()->Lock();
|
||||
fMouseTarget->Window()->SendMessageToClient(&wheelmsg);
|
||||
fMouseTarget->Window()->Unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("\nDesktop::MouseEventHandler(): WARNING: unknown message\n\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Desktop::KeyboardEventHandler(int32 code, BPortLink& msg)
|
||||
{
|
||||
|
||||
switch(code)
|
||||
{
|
||||
case B_KEY_DOWN:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifier-independent ASCII code for the character
|
||||
// 4) int32 repeat count
|
||||
// 5) int32 modifiers
|
||||
// 6) int8[3] UTF-8 data generated
|
||||
// 7) int8 number of bytes to follow containing the
|
||||
// generated string
|
||||
// 8) Character string generated by the keystroke
|
||||
// 9) int8[16] state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode, modifiers;
|
||||
int8 utf[3];
|
||||
char *string = NULL;
|
||||
int32 keystate;
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read(utf, sizeof(utf));
|
||||
msg.ReadString(&string);
|
||||
msg.Read<int32>(&keystate);
|
||||
if (string)
|
||||
free(string);
|
||||
|
||||
if(DISPLAYDRIVER==HWDRIVER)
|
||||
{
|
||||
// Check for workspace change or safe video mode
|
||||
if(scancode>0x01 && scancode<0x0e)
|
||||
{
|
||||
if(scancode==0x0d)
|
||||
{
|
||||
if(modifiers & (B_LEFT_COMMAND_KEY |
|
||||
B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY))
|
||||
{
|
||||
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN. (DisplayDriver API change)
|
||||
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(modifiers & B_CONTROL_KEY)
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n",scancode-1));
|
||||
|
||||
//TODO: SetWorkspace in KeyboardEventHandler
|
||||
//SetWorkspace(scancode-2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Tab key
|
||||
if(scancode==0x26 && (modifiers & B_CONTROL_KEY))
|
||||
{
|
||||
ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
if(deskbar)
|
||||
{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// PrintScreen
|
||||
if(scancode==0xe)
|
||||
{
|
||||
if(GetDisplayDriver())
|
||||
{
|
||||
char filename[128];
|
||||
BEntry entry;
|
||||
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
entry.SetTo(filename);
|
||||
|
||||
while(entry.Exists())
|
||||
{
|
||||
fScreenShotIndex++;
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
}
|
||||
fScreenShotIndex++;
|
||||
GetDisplayDriver()->DumpToFile(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// F12
|
||||
if(scancode>0x1 && scancode<0xe)
|
||||
{
|
||||
if(scancode==0xd)
|
||||
{
|
||||
if(modifiers & (B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY | B_LEFT_OPTION_KEY))
|
||||
{
|
||||
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN. (DisplayDriver API change)
|
||||
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(modifiers & (B_LEFT_SHIFT_KEY | B_LEFT_CONTROL_KEY))
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n",scancode-1));
|
||||
//TODO: SetWorkspace in KeyboardEventHandler
|
||||
//SetWorkspace(scancode-2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Tab
|
||||
if(scancode==0x26 && (modifiers & B_SHIFT_KEY))
|
||||
{
|
||||
STRACE(("Twitcher\n"));
|
||||
ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
if(deskbar)
|
||||
{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pause/Break
|
||||
if(scancode==0x7f)
|
||||
{
|
||||
if(GetDisplayDriver())
|
||||
{
|
||||
char filename[128];
|
||||
BEntry entry;
|
||||
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
entry.SetTo(filename);
|
||||
|
||||
while(entry.Exists())
|
||||
{
|
||||
fScreenShotIndex++;
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
}
|
||||
fScreenShotIndex++;
|
||||
|
||||
GetDisplayDriver()->DumpToFile(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We got this far, so apparently it's safe to pass to the active
|
||||
// window.
|
||||
|
||||
// TODO: Pass on key down message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_KEY_UP:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifier-independent ASCII code for the character
|
||||
// 4) int32 modifiers
|
||||
// 5) int8[3] UTF-8 data generated
|
||||
// 6) int8 number of bytes to follow containing the
|
||||
// generated string
|
||||
// 7) Character string generated by the keystroke
|
||||
// 8) int8[16] state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 ascii;
|
||||
int32 modifiers;
|
||||
int8 utf[3];
|
||||
int8 bytes;
|
||||
char *string;
|
||||
int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&ascii);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read(utf, sizeof(utf));
|
||||
msg.Read<int8>(&bytes);
|
||||
msg.ReadString(&string);
|
||||
msg.Read(keystate, sizeof(keystate));
|
||||
if (string)
|
||||
free(string);
|
||||
|
||||
STRACE(("Key Up: 0x%lx\n",scancode));
|
||||
|
||||
if(DISPLAYDRIVER==HWDRIVER)
|
||||
{
|
||||
// Tab key
|
||||
if(scancode==0x26 && (modifiers & B_CONTROL_KEY))
|
||||
{
|
||||
ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
if(deskbar)
|
||||
{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(scancode==0x26 && (modifiers & B_LEFT_SHIFT_KEY))
|
||||
{
|
||||
ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
if(deskbar)
|
||||
{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We got this far, so apparently it's safe to pass to the active
|
||||
// window.
|
||||
|
||||
// TODO: Pass on key up message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifiers
|
||||
// 4) int32 number of elements in the key state array to follow
|
||||
// 5) int8 state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 modifiers;
|
||||
int32 elements;
|
||||
//int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read<int32>(&elements);
|
||||
//msg.Read(keystate, elements);
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
printf("Unmapped Key Down: 0x%lx\n", scancode);
|
||||
#endif
|
||||
|
||||
// TODO: Pass on unmapped key down message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifiers
|
||||
// 4) int32 number of elements in the key state array to follow
|
||||
// 5) int8 state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 modifiers;
|
||||
int32 elements;
|
||||
//int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read<int32>(&elements);
|
||||
//msg.Read(keystate, elements);
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
printf("Unmapped Key Up: 0x%lx\n", scancode);
|
||||
#endif
|
||||
|
||||
// TODO: Pass on unmapped key up message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_MODIFIERS_CHANGED:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 modifiers
|
||||
// 3) int32 old modifiers
|
||||
// 4) int32 number of elements in the key state array to follow
|
||||
// 5) int8 state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 modifiers;
|
||||
int32 elements;
|
||||
//int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read<int32>(&elements);
|
||||
//msg.Read(keystate, elements);
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
printf("Modifiers Changed\n");
|
||||
#endif
|
||||
|
||||
// TODO: Pass on modifier change message to client window with the focus
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Desktop::SetDragMessage(BMessage* msg)
|
||||
{
|
||||
if (fDragMessage)
|
||||
{
|
||||
delete fDragMessage;
|
||||
fDragMessage = NULL;
|
||||
}
|
||||
|
||||
if (msg)
|
||||
fDragMessage = new BMessage(*msg);
|
||||
}
|
||||
|
||||
BMessage* Desktop::DragMessage(void) const
|
||||
{
|
||||
return fDragMessage;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Methods for various desktop stuff handled by the server
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -936,7 +333,7 @@ void Desktop::RemoveSubsetWindow(WinBorder* wb)
|
||||
for(int32 i=0; i < count; i++)
|
||||
{
|
||||
winBorder = static_cast<WinBorder*>(fWinBorderList.ItemAt(i));
|
||||
if (winBorder->fLevel == B_NORMAL_FEEL)
|
||||
if (winBorder->Level() == B_NORMAL_FEEL)
|
||||
winBorder->Window()->fWinFMWList.RemoveItem(wb);
|
||||
}
|
||||
fLayerLock.Unlock();
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Desktop.cpp
|
||||
// Author: Adi Oanca <adioanca@mymail.ro>
|
||||
// Author: Adi Oanca <adioanca@cotty.iren.ro>
|
||||
// Description: Class used to encapsulate desktop management
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -69,13 +69,6 @@ public:
|
||||
void RemoveWinBorder(WinBorder *winBorder);
|
||||
bool HasWinBorder(WinBorder *winBorder);
|
||||
|
||||
// Input related methods
|
||||
void MouseEventHandler(int32 code, BPortLink& link);
|
||||
void KeyboardEventHandler(int32 code, BPortLink& link);
|
||||
|
||||
void SetDragMessage(BMessage *msg);
|
||||
BMessage *DragMessage(void) const;
|
||||
|
||||
// Methods for various desktop stuff handled by the server
|
||||
void SetScrollBarInfo(const scroll_bar_info &info);
|
||||
scroll_bar_info ScrollBarInfo(void) const;
|
||||
@@ -83,7 +76,6 @@ public:
|
||||
void SetMenuInfo(const menu_info &info);
|
||||
menu_info MenuInfo(void) const;
|
||||
|
||||
|
||||
void UseFFMouse(const bool &useffm);
|
||||
bool FFMouseInUse(void) const;
|
||||
void SetFFMouseMode(const mode_mouse &value);
|
||||
@@ -102,13 +94,9 @@ public:
|
||||
BList fWinBorderList;
|
||||
|
||||
private:
|
||||
BMessage *fDragMessage;
|
||||
|
||||
BList fRootLayerList;
|
||||
RootLayer *fActiveRootLayer;
|
||||
|
||||
WinBorder *fMouseTarget;
|
||||
|
||||
BList fScreenList;
|
||||
Screen *fActiveScreen;
|
||||
|
||||
@@ -116,7 +104,6 @@ private:
|
||||
menu_info fMenuInfo;
|
||||
mode_mouse fMouseMode;
|
||||
bool fFFMouseMode;
|
||||
int32 fScreenShotIndex;
|
||||
};
|
||||
|
||||
extern Desktop *desktop;
|
||||
|
||||
@@ -794,7 +794,13 @@ DDView::DDView(BRect bounds)
|
||||
SetViewColor(B_TRANSPARENT_32_BIT);
|
||||
|
||||
#ifdef ENABLE_INPUT_SERVER_EMULATION
|
||||
serverlink.SetSendPort(find_port(SERVER_INPUT_PORT));
|
||||
port_id serverInputPort = create_port(200, SERVER_INPUT_PORT);
|
||||
if (serverInputPort == B_NO_MORE_PORTS)
|
||||
{
|
||||
debugger("ViewDriver: out of ports\n");
|
||||
return;
|
||||
}
|
||||
serverlink.SetSendPort(serverInputPort);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
//
|
||||
// File Name: Layer.h
|
||||
// Author: DarkWyrm <[email protected]>
|
||||
// Adi Oanca <adioanca@myrealbox.com>
|
||||
// Adi Oanca <adioanca@cotty.iren.com>
|
||||
// Description: Class used for rendering to the frame buffer. One layer per
|
||||
// view on screen and also for window decorators
|
||||
//
|
||||
@@ -133,6 +133,7 @@ public:
|
||||
ServerWindow *Window(void) const { return fServerWin; }
|
||||
virtual bool HasClient(void) { return true; }
|
||||
bool IsServerLayer() const;
|
||||
int32 Level() const { return fLevel; }
|
||||
|
||||
void PruneTree(void);
|
||||
|
||||
@@ -155,7 +156,6 @@ protected:
|
||||
friend class WinBorder;
|
||||
friend class Screen;
|
||||
friend class ServerWindow;
|
||||
friend class Desktop;
|
||||
friend class Workspace;
|
||||
|
||||
BRect fFrame;
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
#include <Window.h>
|
||||
#include <List.h>
|
||||
#include <Message.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <PortLink.h>
|
||||
|
||||
#include "Globals.h"
|
||||
#include "RootLayer.h"
|
||||
@@ -45,6 +47,7 @@
|
||||
#include "ServerConfig.h"
|
||||
#include "FMWList.h"
|
||||
#include "DisplayDriver.h"
|
||||
#include "ServerProtocol.h"
|
||||
|
||||
//#define DEBUG_ROOTLAYER
|
||||
|
||||
@@ -62,7 +65,13 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
|
||||
: Layer(BRect(0,0,0,0), name, 0, B_FOLLOW_ALL, B_WILL_DRAW, driver)
|
||||
{
|
||||
fDesktop = desktop;
|
||||
|
||||
|
||||
fMouseTarget = NULL;
|
||||
fDragMessage = NULL;
|
||||
fScreenShotIndex = 1;
|
||||
|
||||
fQuiting = false;
|
||||
|
||||
//NOTE: be careful about this one.
|
||||
fRootLayer = this;
|
||||
fActiveWorkspace = NULL;
|
||||
@@ -81,14 +90,94 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
|
||||
// easy way to identify this class.
|
||||
fClassID = AS_ROOTLAYER_CLASS;
|
||||
fHidden = false;
|
||||
|
||||
|
||||
fListenPort = find_port(SERVER_INPUT_PORT);
|
||||
if (fListenPort == B_NAME_NOT_FOUND)
|
||||
return;
|
||||
|
||||
// Spawn our working thread
|
||||
fThreadID= spawn_thread(WorkingThread, name, B_REAL_TIME_DISPLAY_PRIORITY, this);
|
||||
if (fThreadID >= 0)
|
||||
resume_thread(fThreadID);
|
||||
|
||||
}
|
||||
|
||||
RootLayer::~RootLayer()
|
||||
{
|
||||
int32 exitValue;
|
||||
fQuiting = true;
|
||||
BPortLink msg(fListenPort, -1);
|
||||
msg.StartMessage(B_QUIT_REQUESTED);
|
||||
msg.EndMessage();
|
||||
msg.Flush();
|
||||
|
||||
wait_for_thread(fThreadID, &exitValue);
|
||||
|
||||
if (fDragMessage)
|
||||
delete fDragMessage;
|
||||
|
||||
// RootLayer object just uses Screen objects, it is not allowed to delete them.
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Thread function for handling input messages and calculating visible regions.
|
||||
\param data Pointer to the app_server to which the thread belongs
|
||||
\return Throwaway value - always 0
|
||||
*/
|
||||
int32 RootLayer::WorkingThread(void *data)
|
||||
{
|
||||
int32 code = 0;
|
||||
status_t err = B_OK;
|
||||
RootLayer *oneRootLayer = (RootLayer*)data;
|
||||
BPortLink messageQueue(-1, oneRootLayer->fListenPort);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
STRACE(("info: RootLayer(%s)::WorkingThread listening on port %ld.\n", oneRootLayer->GetName(), oneRootLayer->fListenPort));
|
||||
err = messageQueue.GetNextReply(&code);
|
||||
|
||||
if(err < B_OK)
|
||||
{
|
||||
STRACE(("WorkingThread: messageQueue.GetNextReply failed\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(code)
|
||||
{
|
||||
// We don't need to do anything with these two, so just pass them
|
||||
// onto the active application. Eventually, we will end up passing
|
||||
// them onto the window which is currently under the cursor.
|
||||
case B_MOUSE_DOWN:
|
||||
case B_MOUSE_UP:
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
case B_MOUSE_MOVED:
|
||||
oneRootLayer->MouseEventHandler(code, messageQueue);
|
||||
break;
|
||||
|
||||
case B_KEY_DOWN:
|
||||
case B_KEY_UP:
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
case B_MODIFIERS_CHANGED:
|
||||
oneRootLayer->KeyboardEventHandler(code, messageQueue);
|
||||
break;
|
||||
|
||||
case B_QUIT_REQUESTED:
|
||||
exit_thread(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
STRACE(("RootLayer(%s)::WorkingThread received unexpected code %lx\n",oneRootLayer->GetName(), oneRootLayer->code));
|
||||
break;
|
||||
}
|
||||
|
||||
// if we still have other messages in our queue, but we really want to quit
|
||||
if (oneRootLayer->fQuiting)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RootLayer::MoveBy(float x, float y)
|
||||
{
|
||||
}
|
||||
@@ -680,6 +769,603 @@ void RootLayer::RemoveAppWindow(WinBorder *wb)
|
||||
WorkspaceAt(i+1)->RemoveWinBorder(wb);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Input related methods
|
||||
//---------------------------------------------------------------------------
|
||||
void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
|
||||
{
|
||||
// TODO: locking mechanism needs SERIOUS rethought
|
||||
switch(code)
|
||||
{
|
||||
case B_MOUSE_DOWN:
|
||||
{
|
||||
// Attached data:
|
||||
// 1) int64 - time of mouse click
|
||||
// 2) float - x coordinate of mouse click
|
||||
// 3) float - y coordinate of mouse click
|
||||
// 4) int32 - modifier keys down
|
||||
// 5) int32 - buttons down
|
||||
// 6) int32 - clicks
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_DOWN;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.where.x);
|
||||
msg.Read<float>(&evt.where.y);
|
||||
msg.Read<int32>(&evt.modifiers);
|
||||
msg.Read<int32>(&evt.buttons);
|
||||
msg.Read<int32>(&evt.clicks);
|
||||
|
||||
// printf("MOUSE DOWN: at (%f, %f)\n", evt.where.x, evt.where.y);
|
||||
|
||||
WinBorder *target=NULL;
|
||||
Workspace *ws=NULL;
|
||||
ws = ActiveWorkspace();
|
||||
target = WinBorderAt(evt.where);
|
||||
if (target)
|
||||
{
|
||||
desktop->fGeneralLock.Lock();
|
||||
fMainLock.Lock();
|
||||
|
||||
STRACE(("Target: %s\n", target->GetName()));
|
||||
STRACE(("Front: %s\n", ws->FrontLayer()->GetName()));
|
||||
STRACE(("Focus: %s\n", ws->FocusLayer()->GetName()));
|
||||
|
||||
WinBorder *previousFocus=NULL;
|
||||
WinBorder *activeFocus=NULL;
|
||||
BRegion invalidRegion;
|
||||
|
||||
BMessage downmsg(B_MOUSE_DOWN);
|
||||
downmsg.AddInt64("when",evt.when);
|
||||
downmsg.AddPoint("where",evt.where);
|
||||
downmsg.AddInt32("modifiers",evt.modifiers);
|
||||
downmsg.AddInt32("buttons",evt.buttons);
|
||||
downmsg.AddInt32("clicks",evt.clicks);
|
||||
|
||||
if (target!=ws->FrontLayer())
|
||||
{
|
||||
ws->BringToFrontANormalWindow(target);
|
||||
ws->SearchAndSetNewFront(target);
|
||||
previousFocus = ws->FocusLayer();
|
||||
ws->SearchAndSetNewFocus(target);
|
||||
activeFocus = ws->FocusLayer();
|
||||
|
||||
activeFocus->Window()->Lock();
|
||||
|
||||
if (target == activeFocus && target->Window()->Flags() & B_WILL_ACCEPT_FIRST_CLICK)
|
||||
target->MouseDown(evt, true);
|
||||
else
|
||||
target->MouseDown(evt, false);
|
||||
|
||||
// may or may not be empty.
|
||||
|
||||
// TODO: B_MOUSE_DOWN: what if modal of floating windows are in front of us?
|
||||
invalidRegion.Include(&(activeFocus->fFull));
|
||||
invalidRegion.Include(&(activeFocus->fTopLayer->fFull));
|
||||
activeFocus->fParent->RebuildAndForceRedraw(invalidRegion, activeFocus);
|
||||
|
||||
if (previousFocus != activeFocus && previousFocus)
|
||||
{
|
||||
if (previousFocus->fVisible.CountRects() > 0)
|
||||
{
|
||||
invalidRegion.MakeEmpty();
|
||||
invalidRegion.Include(&(previousFocus->fVisible));
|
||||
activeFocus->fParent->Invalidate(invalidRegion);
|
||||
}
|
||||
}
|
||||
|
||||
fMouseTarget = target;
|
||||
|
||||
STRACE(("2Target: %s\n", target->GetName()));
|
||||
STRACE(("2Front: %s\n", ws->FrontLayer()->GetName()));
|
||||
STRACE(("2Focus: %s\n", ws->FocusLayer()->GetName()));
|
||||
|
||||
fMouseTarget->Window()->SendMessageToClient(&downmsg);
|
||||
activeFocus->Window()->Unlock();
|
||||
}
|
||||
else // target == ws->FrontLayer()
|
||||
{
|
||||
// only if target has the focus!
|
||||
if (target == ws->FocusLayer())
|
||||
{
|
||||
target->Window()->Lock();
|
||||
target->MouseDown(evt, true);
|
||||
target->Window()->SendMessageToClient(&downmsg);
|
||||
target->Window()->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
previousFocus = ws->FocusLayer();
|
||||
ws->SearchAndSetNewFocus(target);
|
||||
activeFocus = ws->FocusLayer();
|
||||
|
||||
activeFocus->Window()->Lock();
|
||||
|
||||
if (target == activeFocus && target->Window()->Flags() & B_WILL_ACCEPT_FIRST_CLICK)
|
||||
target->MouseDown(evt, true);
|
||||
else
|
||||
target->MouseDown(evt, false);
|
||||
|
||||
// may or may not be empty.
|
||||
|
||||
// TODO: B_MOUSE_DOWN: what if modal of floating windows are in front of us?
|
||||
invalidRegion.Include(&(activeFocus->fFull));
|
||||
invalidRegion.Include(&(activeFocus->fTopLayer->fFull));
|
||||
activeFocus->fParent->RebuildAndForceRedraw(invalidRegion, activeFocus);
|
||||
|
||||
if (previousFocus != activeFocus && previousFocus)
|
||||
{
|
||||
if (previousFocus->fVisible.CountRects() > 0)
|
||||
{
|
||||
invalidRegion.MakeEmpty();
|
||||
invalidRegion.Include(&(previousFocus->fVisible));
|
||||
activeFocus->fParent->Invalidate(invalidRegion);
|
||||
}
|
||||
}
|
||||
fMouseTarget = target;
|
||||
fMouseTarget->Window()->SendMessageToClient(&downmsg);
|
||||
|
||||
activeFocus->Window()->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
fMainLock.Unlock();
|
||||
desktop->fGeneralLock.Unlock();
|
||||
}
|
||||
else // target == NULL
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
case B_MOUSE_UP:
|
||||
{
|
||||
// Attached data:
|
||||
// 1) int64 - time of mouse click
|
||||
// 2) float - x coordinate of mouse click
|
||||
// 3) float - y coordinate of mouse click
|
||||
// 4) int32 - modifier keys down
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_UP;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.where.x);
|
||||
msg.Read<float>(&evt.where.y);
|
||||
msg.Read<int32>(&evt.modifiers);
|
||||
|
||||
if (!fMouseTarget)
|
||||
{
|
||||
WinBorder *target = WinBorderAt(BPoint(evt.where.x, evt.where.y));
|
||||
if(!target)
|
||||
break;
|
||||
fMouseTarget=target;
|
||||
}
|
||||
|
||||
fMouseTarget->Window()->Lock();
|
||||
fMouseTarget->MouseUp(evt);
|
||||
|
||||
BMessage upmsg(B_MOUSE_UP);
|
||||
upmsg.AddInt64("when",evt.when);
|
||||
upmsg.AddPoint("where",evt.where);
|
||||
upmsg.AddInt32("modifiers",evt.modifiers);
|
||||
|
||||
fMouseTarget->Window()->SendMessageToClient(&upmsg);
|
||||
fMouseTarget->Window()->Unlock();
|
||||
|
||||
STRACE(("MOUSE UP: at (%f, %f)\n", evt.where.x, evt.where.y));
|
||||
|
||||
break;
|
||||
}
|
||||
case B_MOUSE_MOVED:
|
||||
{
|
||||
// Attached data:
|
||||
// 1) int64 - time of mouse click
|
||||
// 2) float - x coordinate of mouse click
|
||||
// 3) float - y coordinate of mouse click
|
||||
// 4) int32 - buttons down
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_MOVED;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.where.x);
|
||||
msg.Read<float>(&evt.where.y);
|
||||
msg.Read<int32>(&evt.buttons);
|
||||
|
||||
GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y);
|
||||
|
||||
if (!fMouseTarget)
|
||||
{
|
||||
WinBorder *target = WinBorderAt(BPoint(evt.where.x, evt.where.y));
|
||||
if(!target)
|
||||
break;
|
||||
fMouseTarget=target;
|
||||
}
|
||||
|
||||
fMouseTarget->Window()->Lock();
|
||||
fMouseTarget->MouseMoved(evt);
|
||||
|
||||
BMessage movemsg(B_MOUSE_MOVED);
|
||||
movemsg.AddInt64("when",evt.when);
|
||||
movemsg.AddPoint("where",evt.where);
|
||||
movemsg.AddInt32("buttons",evt.buttons);
|
||||
|
||||
fMouseTarget->Window()->SendMessageToClient(&movemsg);
|
||||
fMouseTarget->Window()->Unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
{
|
||||
// FEATURE: This is a tentative change: mouse wheel messages are always sent to the window
|
||||
// under the cursor. It's pretty stupid to send it to the active window unless a particular
|
||||
// view has locked focus via SetMouseEventMask
|
||||
|
||||
PointerEvent evt;
|
||||
evt.code = B_MOUSE_WHEEL_CHANGED;
|
||||
msg.Read<int64>(&evt.when);
|
||||
msg.Read<float>(&evt.wheel_delta_x);
|
||||
msg.Read<float>(&evt.wheel_delta_y);
|
||||
|
||||
BMessage wheelmsg(B_MOUSE_WHEEL_CHANGED);
|
||||
wheelmsg.AddInt64("when",evt.when);
|
||||
wheelmsg.AddFloat("be:wheel_delta_x",evt.wheel_delta_x);
|
||||
wheelmsg.AddFloat("be:wheel_delta_y",evt.wheel_delta_y);
|
||||
|
||||
if(!fMouseTarget)
|
||||
{
|
||||
fMouseTarget = WinBorderAt(GetDisplayDriver()->GetCursorPosition());
|
||||
|
||||
// We do nothing because there ain't a window to receive the message
|
||||
if(!fMouseTarget)
|
||||
break;
|
||||
}
|
||||
|
||||
fMouseTarget->Window()->Lock();
|
||||
fMouseTarget->Window()->SendMessageToClient(&wheelmsg);
|
||||
fMouseTarget->Window()->Unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("\nDesktop::MouseEventHandler(): WARNING: unknown message\n\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
|
||||
{
|
||||
|
||||
switch(code)
|
||||
{
|
||||
case B_KEY_DOWN:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifier-independent ASCII code for the character
|
||||
// 4) int32 repeat count
|
||||
// 5) int32 modifiers
|
||||
// 6) int8[3] UTF-8 data generated
|
||||
// 7) int8 number of bytes to follow containing the
|
||||
// generated string
|
||||
// 8) Character string generated by the keystroke
|
||||
// 9) int8[16] state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode, modifiers;
|
||||
int8 utf[3];
|
||||
char *string = NULL;
|
||||
int32 keystate;
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read(utf, sizeof(utf));
|
||||
msg.ReadString(&string);
|
||||
msg.Read<int32>(&keystate);
|
||||
if (string)
|
||||
free(string);
|
||||
|
||||
if(DISPLAYDRIVER==HWDRIVER)
|
||||
{
|
||||
// Check for workspace change or safe video mode
|
||||
if(scancode>0x01 && scancode<0x0e)
|
||||
{
|
||||
if(scancode==0x0d)
|
||||
{
|
||||
if(modifiers & (B_LEFT_COMMAND_KEY |
|
||||
B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY))
|
||||
{
|
||||
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN. (DisplayDriver API change)
|
||||
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(modifiers & B_CONTROL_KEY)
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n",scancode-1));
|
||||
|
||||
//TODO: SetWorkspace in KeyboardEventHandler
|
||||
//SetWorkspace(scancode-2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Tab key
|
||||
if(scancode==0x26 && (modifiers & B_CONTROL_KEY))
|
||||
{
|
||||
//ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
//if(deskbar)
|
||||
//{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
//}
|
||||
}
|
||||
|
||||
// PrintScreen
|
||||
if(scancode==0xe)
|
||||
{
|
||||
if(GetDisplayDriver())
|
||||
{
|
||||
char filename[128];
|
||||
BEntry entry;
|
||||
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
entry.SetTo(filename);
|
||||
|
||||
while(entry.Exists())
|
||||
{
|
||||
fScreenShotIndex++;
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
}
|
||||
fScreenShotIndex++;
|
||||
GetDisplayDriver()->DumpToFile(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// F12
|
||||
if(scancode>0x1 && scancode<0xe)
|
||||
{
|
||||
if(scancode==0xd)
|
||||
{
|
||||
if(modifiers & (B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY | B_LEFT_OPTION_KEY))
|
||||
{
|
||||
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN. (DisplayDriver API change)
|
||||
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(modifiers & (B_LEFT_SHIFT_KEY | B_LEFT_CONTROL_KEY))
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n",scancode-1));
|
||||
//TODO: SetWorkspace in KeyboardEventHandler
|
||||
//SetWorkspace(scancode-2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Tab
|
||||
if(scancode==0x26 && (modifiers & B_SHIFT_KEY))
|
||||
{
|
||||
STRACE(("Twitcher\n"));
|
||||
//ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
//if(deskbar)
|
||||
//{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
//}
|
||||
}
|
||||
|
||||
// Pause/Break
|
||||
if(scancode==0x7f)
|
||||
{
|
||||
if(GetDisplayDriver())
|
||||
{
|
||||
char filename[128];
|
||||
BEntry entry;
|
||||
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
entry.SetTo(filename);
|
||||
|
||||
while(entry.Exists())
|
||||
{
|
||||
fScreenShotIndex++;
|
||||
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
|
||||
}
|
||||
fScreenShotIndex++;
|
||||
|
||||
GetDisplayDriver()->DumpToFile(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We got this far, so apparently it's safe to pass to the active
|
||||
// window.
|
||||
|
||||
// TODO: Pass on key down message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_KEY_UP:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifier-independent ASCII code for the character
|
||||
// 4) int32 modifiers
|
||||
// 5) int8[3] UTF-8 data generated
|
||||
// 6) int8 number of bytes to follow containing the
|
||||
// generated string
|
||||
// 7) Character string generated by the keystroke
|
||||
// 8) int8[16] state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 ascii;
|
||||
int32 modifiers;
|
||||
int8 utf[3];
|
||||
int8 bytes;
|
||||
char *string;
|
||||
int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&ascii);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read(utf, sizeof(utf));
|
||||
msg.Read<int8>(&bytes);
|
||||
msg.ReadString(&string);
|
||||
msg.Read(keystate, sizeof(keystate));
|
||||
if (string)
|
||||
free(string);
|
||||
|
||||
STRACE(("Key Up: 0x%lx\n",scancode));
|
||||
|
||||
if(DISPLAYDRIVER==HWDRIVER)
|
||||
{
|
||||
// Tab key
|
||||
if(scancode==0x26 && (modifiers & B_CONTROL_KEY))
|
||||
{
|
||||
//ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
//if(deskbar)
|
||||
//{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
//}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(scancode==0x26 && (modifiers & B_LEFT_SHIFT_KEY))
|
||||
{
|
||||
//ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
//if(deskbar)
|
||||
//{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
// We got this far, so apparently it's safe to pass to the active
|
||||
// window.
|
||||
|
||||
// TODO: Pass on key up message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifiers
|
||||
// 4) int32 number of elements in the key state array to follow
|
||||
// 5) int8 state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 modifiers;
|
||||
int32 elements;
|
||||
//int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read<int32>(&elements);
|
||||
//msg.Read(keystate, elements);
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
printf("Unmapped Key Down: 0x%lx\n", scancode);
|
||||
#endif
|
||||
|
||||
// TODO: Pass on unmapped key down message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 raw key code (scancode)
|
||||
// 3) int32 modifiers
|
||||
// 4) int32 number of elements in the key state array to follow
|
||||
// 5) int8 state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 modifiers;
|
||||
int32 elements;
|
||||
//int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read<int32>(&elements);
|
||||
//msg.Read(keystate, elements);
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
printf("Unmapped Key Up: 0x%lx\n", scancode);
|
||||
#endif
|
||||
|
||||
// TODO: Pass on unmapped key up message to client window with the focus
|
||||
break;
|
||||
}
|
||||
case B_MODIFIERS_CHANGED:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) int64 bigtime_t object of when the message was sent
|
||||
// 2) int32 modifiers
|
||||
// 3) int32 old modifiers
|
||||
// 4) int32 number of elements in the key state array to follow
|
||||
// 5) int8 state of all keys
|
||||
|
||||
bigtime_t time;
|
||||
int32 scancode;
|
||||
int32 modifiers;
|
||||
int32 elements;
|
||||
//int8 keystate[16];
|
||||
|
||||
msg.Read<bigtime_t>(&time);
|
||||
msg.Read<int32>(&scancode);
|
||||
msg.Read<int32>(&modifiers);
|
||||
msg.Read<int32>(&elements);
|
||||
//msg.Read(keystate, elements);
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
printf("Modifiers Changed\n");
|
||||
#endif
|
||||
|
||||
// TODO: Pass on modifier change message to client window with the focus
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RootLayer::SetDragMessage(BMessage* msg)
|
||||
{
|
||||
if (fDragMessage)
|
||||
{
|
||||
delete fDragMessage;
|
||||
fDragMessage = NULL;
|
||||
}
|
||||
|
||||
if (msg)
|
||||
fDragMessage = new BMessage(*msg);
|
||||
}
|
||||
|
||||
BMessage* RootLayer::DragMessage(void) const
|
||||
{
|
||||
return fDragMessage;
|
||||
}
|
||||
|
||||
// DEBUG methods
|
||||
|
||||
void RootLayer::PrintToStream()
|
||||
{
|
||||
printf("\nRootLayer '%s' internals:\n", GetName());
|
||||
|
||||
@@ -94,7 +94,17 @@ public:
|
||||
virtual bool HasClient(void) { return false; }
|
||||
|
||||
void AddWinBorderToWorkspaces(WinBorder *winBorder, uint32 wks);
|
||||
|
||||
// Input related methods
|
||||
void MouseEventHandler(int32 code, BPortLink& link);
|
||||
void KeyboardEventHandler(int32 code, BPortLink& link);
|
||||
|
||||
void SetDragMessage(BMessage *msg);
|
||||
BMessage *DragMessage(void) const;
|
||||
|
||||
static int32 WorkingThread(void *data);
|
||||
|
||||
// Debug methods
|
||||
void PrintToStream(void);
|
||||
|
||||
// "Private" to app_server :-) - they should not be used
|
||||
@@ -105,6 +115,11 @@ public:
|
||||
|
||||
private:
|
||||
Desktop *fDesktop;
|
||||
BMessage *fDragMessage;
|
||||
WinBorder *fMouseTarget;
|
||||
|
||||
thread_id fThreadID;
|
||||
port_id fListenPort;
|
||||
|
||||
BList fScreenPtrList;
|
||||
int32 fRows;
|
||||
@@ -115,6 +130,9 @@ private:
|
||||
|
||||
BList fWorkspaceList;
|
||||
Workspace *fActiveWorkspace;
|
||||
|
||||
int32 fScreenShotIndex;
|
||||
bool fQuiting;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2215,7 +2215,7 @@ int32 ServerWindow::MonitorWin(void *data)
|
||||
|
||||
while(!quitting)
|
||||
{
|
||||
printf("info: ServerWindow::MonitorWin listening on port %ld.\n", win->fMessagePort);
|
||||
// printf("info: ServerWindow::MonitorWin listening on port %ld.\n", win->fMessagePort);
|
||||
code = AS_CLIENT_DEAD;
|
||||
err = ses->GetNextMessage(&code);
|
||||
if (err < B_OK)
|
||||
|
||||
@@ -83,7 +83,13 @@ VDView::VDView(BRect bounds)
|
||||
|
||||
// This link for sending mouse messages to the OBAppServer.
|
||||
// This is only to take the place of the Input Server.
|
||||
serverlink = new BPortLink(find_port(SERVER_INPUT_PORT));
|
||||
port_id serverInputPort = create_port(200, SERVER_INPUT_PORT);
|
||||
if (serverInputPort == B_NO_MORE_PORTS)
|
||||
{
|
||||
debugger("ViewDriver: out of ports\n");
|
||||
return;
|
||||
}
|
||||
serverlink = new BPortLink(serverInputPort);
|
||||
|
||||
// Create a cursor which isn't just a box
|
||||
cursor=new BBitmap(BRect(0,0,20,20),B_RGBA32,true);
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
protected:
|
||||
friend class Layer;
|
||||
friend class ServerWindow;
|
||||
friend class Desktop;
|
||||
friend class RootLayer;
|
||||
|
||||
Decorator *fDecorator;
|
||||
Layer *fTopLayer;
|
||||
|
||||
Reference in New Issue
Block a user