Added initial method addons support

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9445 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2004-10-22 13:05:35 +00:00
parent 25b194b98f
commit f40fc44ef4
12 changed files with 888 additions and 34 deletions

View File

@ -8,10 +8,12 @@
#include <Autolock.h>
#include <Deskbar.h>
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Roster.h>
#include <String.h>
#include <image.h>
@ -21,7 +23,7 @@
#include "AddOnManager.h"
#include "InputServer.h"
#include "InputServerTypes.h"
#include "MethodReplicant.h"
AddOnManager::AddOnManager(bool safeMode)
: BLooper("addon_manager"),
@ -218,6 +220,12 @@ AddOnManager::UnregisterAddOn(BEntry &entry)
break;
}
}
if (fMethodList.CountItems()<=0) {
// we remove the method replicant
BDeskbar().RemoveItem(REPLICANT_CTL_NAME);
((InputServer*)be_app)->SetMethodReplicant(NULL);
}
}
return B_OK;
@ -408,6 +416,144 @@ AddOnManager::RegisterMethod(BInputServerMethod *method, const entry_ref &ref, i
BAutolock lock2(InputServer::gInputMethodListLocker);
InputServer::gInputMethodList.AddItem(method);
if (((InputServer*)be_app)->MethodReplicant() == NULL) {
app_info info;
be_app->GetAppInfo(&info);
status_t err = BDeskbar().AddItem(&info.ref);
if (err!=B_OK) {
PRINTERR(("Deskbar refuses to add method replicant\n"));
}
BMessage request(B_GET_PROPERTY);
BMessenger to;
BMessenger status;
request.AddSpecifier("Messenger");
request.AddSpecifier("Shelf");
// In the Deskbar the Shelf is in the View "Status" in Window "Deskbar"
request.AddSpecifier("View", "Status");
request.AddSpecifier("Window", "Deskbar");
to = BMessenger("application/x-vnd.Be-TSKB", -1);
BMessage reply;
if ((to.SendMessage(&request, &reply) == B_OK)
&& (reply.FindMessenger("result", &status) == B_OK)) {
// enum replicant in Status view
int32 index = 0;
int32 uid;
while ((uid = GetReplicantAt(status, index++)) >= B_OK) {
BMessage rep_info;
if (GetReplicantName(status, uid, &rep_info) != B_OK) {
continue;
}
const char *name;
if ((rep_info.FindString("result", &name) == B_OK)
&& (strcmp(name, REPLICANT_CTL_NAME)==0)) {
BMessage rep_view;
if (GetReplicantView(status, uid, &rep_view)==0) {
BMessenger result;
if (rep_view.FindMessenger("result", &result) == B_OK) {
((InputServer*)be_app)->SetMethodReplicant(new BMessenger(result));
}
}
}
}
}
}
}
//
int32
AddOnManager::GetReplicantAt(BMessenger target, int32 index) const
{
/*
So here we want to get the Unique ID of the replicant at the given index
in the target Shelf.
*/
BMessage request(B_GET_PROPERTY);// We're getting the ID property
BMessage reply;
status_t err;
request.AddSpecifier("ID");// want the ID
request.AddSpecifier("Replicant", index);// of the index'th replicant
if ((err = target.SendMessage(&request, &reply)) != B_OK)
return err;
int32 uid;
if ((err = reply.FindInt32("result", &uid)) != B_OK)
return err;
return uid;
}
//
status_t
AddOnManager::GetReplicantName(BMessenger target, int32 uid, BMessage *reply) const
{
/*
We send a message to the target shelf, asking it for the Name of the
replicant with the given unique id.
*/
BMessage request(B_GET_PROPERTY);
BMessage uid_specifier(B_ID_SPECIFIER);// specifying via ID
status_t err;
status_t e;
request.AddSpecifier("Name");// ask for the Name of the replicant
// IDs are specified using code like the following 3 lines:
uid_specifier.AddInt32("id", uid);
uid_specifier.AddString("property", "Replicant");
request.AddSpecifier(&uid_specifier);
if ((err = target.SendMessage(&request, reply)) != B_OK)
return err;
if (((err = reply->FindInt32("error", &e)) != B_OK) || (e != B_OK))
return err ? err : e;
return B_OK;
}
//
status_t
AddOnManager::GetReplicantView(BMessenger target, int32 uid, BMessage *reply) const
{
/*
We send a message to the target shelf, asking it for the Name of the
replicant with the given unique id.
*/
BMessage request(B_GET_PROPERTY);
BMessage uid_specifier(B_ID_SPECIFIER);// specifying via ID
status_t err;
status_t e;
request.AddSpecifier("View");// ask for the Name of the replicant
// IDs are specified using code like the following 3 lines:
uid_specifier.AddInt32("id", uid);
uid_specifier.AddString("property", "Replicant");
request.AddSpecifier(&uid_specifier);
if ((err = target.SendMessage(&request, reply)) != B_OK)
return err;
if (((err = reply->FindInt32("error", &e)) != B_OK) || (e != B_OK))
return err ? err : e;
return B_OK;
}

View File

@ -44,6 +44,10 @@ class AddOnManager : public BLooper {
status_t HandleControlDevices(BMessage*, BMessage*);
status_t HandleSystemShuttingDown(BMessage*, BMessage*);
status_t HandleNodeMonitor(BMessage*);
int32 GetReplicantAt(BMessenger target, int32 index) const;
status_t GetReplicantName(BMessenger target, int32 uid, BMessage *reply) const;
status_t GetReplicantView(BMessenger target, int32 uid, BMessage *reply) const;
private:
struct device_info {

View File

@ -31,6 +31,7 @@
#include <stdio.h>
#include <Deskbar.h>
#include <Directory.h>
#include <Entry.h>
#include <File.h>
@ -38,11 +39,13 @@
#include <Locker.h>
#include <Message.h>
#include <Path.h>
#include <Roster.h>
#include <String.h>
#include <OS.h>
#include "InputServer.h"
#include "InputServerTypes.h"
#include "MethodReplicant.h"
// include app_server headers for communication
#include <PortLink.h>
@ -63,13 +66,13 @@ extern "C" status_t _kget_safemode_option_(char* name, uint8 *p1, uint32 *p2);
// Static InputServer member variables.
//
BList InputServer::gInputDeviceList;
BLocker InputServer::gInputDeviceListLocker;
BLocker InputServer::gInputDeviceListLocker("is_device_queue_sem");
BList InputServer::gInputFilterList;
BLocker InputServer::gInputFilterListLocker;
BLocker InputServer::gInputFilterListLocker("is_filter_queue_sem");
BList InputServer::gInputMethodList;
BLocker InputServer::gInputMethodListLocker;
BLocker InputServer::gInputMethodListLocker("is_method_queue_sem");
DeviceManager InputServer::gDeviceManager;
@ -77,6 +80,17 @@ DeviceManager InputServer::gDeviceManager;
FILE *InputServer::sLogFile = NULL;
#endif
extern "C" _EXPORT BView* instantiate_deskbar_item();
BView *
instantiate_deskbar_item()
{
return new MethodReplicant(INPUTSERVER_SIGNATURE);
}
/*
*
*/
@ -152,7 +166,12 @@ InputServer::InputServer(void) : BApplication(INPUTSERVER_SIGNATURE),
InitKeyboardMouseStates();
fAddOnManager = new AddOnManager(SafeMode());
fAddOnManager->LoadState();
fAddOnManager->LoadState();
//BDeskbar().AddItem(new ::MethodReplicant);
BMessenger messenger(this);
BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED);
}
/*
@ -457,6 +476,18 @@ InputServer::MessageReceived(BMessage *message)
case SYSTEM_SHUTTING_DOWN:
fAddOnManager->PostMessage(message);
return;
case B_SOME_APP_LAUNCHED: {
const char *signature;
if (message->FindString("be:signature", &signature)==B_OK) {
PRINT(("input_server : %s\n", signature));
if (strcmp(signature, "application/x-vnd.Be-TSKB")==0) {
}
}
return;
}
break;
default:
{
return;
@ -473,8 +504,13 @@ InputServer::MessageReceived(BMessage *message)
* Descr:
*/
void
InputServer::HandleSetMethod(BMessage *)
InputServer::HandleSetMethod(BMessage *message)
{
int32 cookie;
if (message->FindInt32("cookie", &cookie) == B_OK) {
_BMethodAddOn_ *addon = (_BMethodAddOn_*)cookie;
SetActiveMethod(addon);
}
}
@ -907,9 +943,10 @@ InputServer::EnqueueMethodMessage(BMessage *message)
* Descr:
*/
status_t
InputServer::UnlockMethodQueue(void)
InputServer::UnlockMethodQueue()
{
return 0;
gInputMethodListLocker.Unlock();
return B_OK;
}
@ -918,9 +955,10 @@ InputServer::UnlockMethodQueue(void)
* Descr:
*/
status_t
InputServer::LockMethodQueue(void)
InputServer::LockMethodQueue()
{
return 0;
gInputMethodListLocker.Lock();
return B_OK;
}
@ -931,6 +969,9 @@ InputServer::LockMethodQueue(void)
status_t
InputServer::SetNextMethod(bool)
{
LockMethodQueue();
UnlockMethodQueue();
return 0;
}
@ -939,12 +980,16 @@ InputServer::SetNextMethod(bool)
* Method: InputServer::SetActiveMethod()
* Descr:
*/
/*
InputServer::SetActiveMethod(_BMethodAddOn_ *)
void
InputServer::SetActiveMethod(_BMethodAddOn_ *addon)
{
return 0;
if (fActiveMethod)
fActiveMethod->MethodActivated(false);
fActiveMethod = addon;
if (fActiveMethod)
fActiveMethod->MethodActivated(true);
}
*/
/*
@ -952,9 +997,16 @@ InputServer::SetActiveMethod(_BMethodAddOn_ *)
* Descr:
*/
const BMessenger*
InputServer::MethodReplicant(void)
InputServer::MethodReplicant()
{
return NULL;
return fReplicantMessenger;
}
void
InputServer::SetMethodReplicant(const BMessenger *messenger)
{
fReplicantMessenger = messenger;
}
@ -968,7 +1020,7 @@ InputServer::EventLoop()
CALLED();
fEventLooperPort = create_port(100, "obos_is_event_port");
if(fEventLooperPort < 0) {
PRINTERR(("OBOS InputServer: create_port error: (0x%x) %s\n", fEventLooperPort, strerror(fEventLooperPort)));
PRINTERR(("InputServer: create_port error: (0x%x) %s\n", fEventLooperPort, strerror(fEventLooperPort)));
}
fISPortThread = spawn_thread(ISPortWatcher, "_input_server_event_loop_", B_REAL_TIME_DISPLAY_PRIORITY+3, this);
resume_thread(fISPortThread);
@ -984,7 +1036,7 @@ InputServer::EventLoop()
bool
InputServer::EventLoopRunning(void)
{
return true;
return fEventLooperPort > -1;
}

View File

@ -80,10 +80,19 @@ class _BDeviceAddOn_
class _BMethodAddOn_
{
public:
_BMethodAddOn_(BInputServerMethod *method)
: fMethod(method) {};
_BMethodAddOn_(BInputServerMethod *method, const char* name, const uchar *icon);
~_BMethodAddOn_();
status_t SetName(const char *name);
status_t SetIcon(const uchar *icon);
status_t SetMenu(const BMenu *menu, const BMessenger &messenger);
status_t MethodActivated(bool activate);
private:
BInputServerMethod *fMethod;
char *fName;
uchar fIcon[16*16*1];
const BMenu *fMenu;
BMessenger fMessenger;
};
/*****************************************************************************/
@ -130,11 +139,11 @@ public:
status_t UnlockMethodQueue(void);
status_t LockMethodQueue(void);
status_t SetNextMethod(bool);
//SetActiveMethod(_BMethodAddOn_*);
void SetActiveMethod(_BMethodAddOn_*);
const BMessenger* MethodReplicant(void);
status_t EventLoop();
static bool EventLoopRunning(void);
void SetMethodReplicant(const BMessenger *);
status_t EventLoop();
bool EventLoopRunning(void);
bool DispatchEvents(BList*);
int DispatchEvent(BMessage*);
@ -201,6 +210,9 @@ private:
BScreen fScreen;
BRect fFrame;
_BMethodAddOn_ *fActiveMethod;
const BMessenger *fReplicantMessenger;
#ifndef COMPILE_FOR_R5
// added this to communicate via portlink

View File

@ -29,8 +29,10 @@
/*****************************************************************************/
#include <InputServerMethod.h>
#include <Menu.h>
#include <Messenger.h>
#include "InputServer.h"
#include "InputServerTypes.h"
/**
* Method: BInputServerMethod::BInputServerMethod()
@ -39,7 +41,8 @@
BInputServerMethod::BInputServerMethod(const char *name,
const uchar *icon)
{
fOwner = new _BMethodAddOn_(this);
CALLED();
fOwner = new _BMethodAddOn_(this, name, icon);
}
@ -49,6 +52,7 @@ BInputServerMethod::BInputServerMethod(const char *name,
*/
BInputServerMethod::~BInputServerMethod()
{
CALLED();
delete fOwner;
}
@ -82,9 +86,7 @@ BInputServerMethod::EnqueueMessage(BMessage *message)
status_t
BInputServerMethod::SetName(const char *name)
{
status_t dummy;
return dummy;
return fOwner->SetName(name);
}
@ -95,9 +97,7 @@ BInputServerMethod::SetName(const char *name)
status_t
BInputServerMethod::SetIcon(const uchar *icon)
{
status_t dummy;
return dummy;
return fOwner->SetIcon(icon);
}
@ -109,9 +109,7 @@ status_t
BInputServerMethod::SetMenu(const BMenu *menu,
const BMessenger target)
{
status_t dummy;
return dummy;
return fOwner->SetMenu(menu, target);
}
@ -155,3 +153,72 @@ BInputServerMethod::_ReservedInputServerMethod4()
}
_BMethodAddOn_::_BMethodAddOn_(BInputServerMethod *method, const char *name,
const uchar *icon)
: fMethod(method),
fMenu(NULL)
{
fName = strdup(name);
memcpy(fIcon, icon, 16*16*1);
}
_BMethodAddOn_::~_BMethodAddOn_()
{
free(fName);
delete fMenu;
}
status_t
_BMethodAddOn_::SetName(const char* name)
{
if (fName)
free(fName);
if (name)
fName = strdup(name);
BMessage msg(IS_UPDATE_NAME);
msg.AddInt32("cookie", (uint32)this);
msg.AddString("name", name);
return ((InputServer*)be_app)->MethodReplicant()->SendMessage(&msg);
}
status_t
_BMethodAddOn_::SetIcon(const uchar* icon)
{
memcpy(fIcon, icon, 16*16*1);
BMessage msg(IS_UPDATE_ICON);
msg.AddInt32("cookie", (uint32)this);
msg.AddData("icon", B_RAW_TYPE, icon, 16*16*1);
return ((InputServer*)be_app)->MethodReplicant()->SendMessage(&msg);
}
status_t
_BMethodAddOn_::SetMenu(const BMenu *menu, const BMessenger &messenger)
{
if (fMenu)
delete fMenu;
fMenu = menu;
fMessenger = messenger;
BMessage msg(IS_UPDATE_MENU);
msg.AddInt32("cookie", (uint32)this);
BMessage menuMsg;
menu->Archive(&menuMsg);
msg.AddMessage("menu", &menuMsg);
msg.AddMessenger("target", messenger);
return ((InputServer*)be_app)->MethodReplicant()->SendMessage(&msg);
}
status_t
_BMethodAddOn_::MethodActivated(bool activate)
{
if (fMethod)
return fMethod->MethodActivated(activate);
return B_ERROR;
}

View File

@ -51,6 +51,9 @@ Server input_server :
SystemKeymap.cpp
MethodReplicant.cpp
MethodMenuItem.cpp
# storage
AddOnMonitor.cpp
AddOnMonitorHandler.cpp

View File

@ -0,0 +1,101 @@
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
// Copyright (c) 2004, Haiku
//
// This software is part of the Haiku distribution and is covered
// by the Haiku license.
//
//
// File: MethodMenuItem.cpp
// Authors: Jérôme Duval,
//
// Description: Input Server
// Created: October 19, 2004
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#include <string.h>
#include "MethodMenuItem.h"
MethodMenuItem::MethodMenuItem(int32 cookie, const char* name, const uchar* icon, BMenu *subMenu, BMessenger &messenger)
: BMenuItem(subMenu),
fIcon(BRect(0, 0, MENUITEM_ICON_SIZE - 1, MENUITEM_ICON_SIZE - 1), B_CMAP8),
fCookie(cookie)
{
SetLabel(name);
fIcon.SetBits(icon, MENUITEM_ICON_SIZE * MENUITEM_ICON_SIZE, 0, B_CMAP8);
fMessenger = messenger;
}
MethodMenuItem::MethodMenuItem(int32 cookie, const char* name, const uchar* icon)
: BMenuItem(name, NULL),
fIcon(BRect(0, 0, MENUITEM_ICON_SIZE - 1, MENUITEM_ICON_SIZE - 1), B_CMAP8),
fCookie(cookie)
{
fIcon.SetBits(icon, MENUITEM_ICON_SIZE * MENUITEM_ICON_SIZE, 0, B_CMAP8);
}
MethodMenuItem::~MethodMenuItem()
{
}
void
MethodMenuItem::SetName(const char *name)
{
SetLabel(name);
}
void
MethodMenuItem::SetIcon(const uchar *icon)
{
fIcon.SetBits(icon, MENUITEM_ICON_SIZE * MENUITEM_ICON_SIZE, 0, B_CMAP8);
}
void
MethodMenuItem::GetContentSize(float *width, float *height)
{
*width = be_plain_font->StringWidth(Label()) + MENUITEM_ICON_SIZE + 3;
font_height fheight;
be_plain_font->GetHeight(&fheight);
*height = fheight.ascent + fheight.descent + fheight.leading - 2;
if (*height < MENUITEM_ICON_SIZE)
*height = MENUITEM_ICON_SIZE;
}
/*
void
MethodMenuItem::Draw()
{
BMenu *menu = Menu();
menu->PushState();
menu->MovePenTo(ContentLocation());
DrawContent();
menu->PopState();
BMenuItem::Draw();
}*/
void
MethodMenuItem::DrawContent()
{
BMenu *menu = Menu();
BRect frame(Frame());
BPoint contLoc = ContentLocation();
menu->SetDrawingMode(B_OP_OVER);
menu->MovePenTo(contLoc);
menu->DrawBitmapAsync(&fIcon);
menu->SetDrawingMode(B_OP_COPY);
menu->MovePenBy(MENUITEM_ICON_SIZE + 3, 2);
BMenuItem::DrawContent();
}

View File

@ -0,0 +1,50 @@
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
// Copyright (c) 2004, Haiku
//
// This software is part of the Haiku distribution and is covered
// by the Haiku license.
//
//
// File: MethodMenuItem.h
// Authors: Jérôme Duval,
//
// Description: Input Server
// Created: October 19, 2004
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#ifndef METHOD_MENUITEM_H_
#define METHOD_MENUITEM_H_
#include <Bitmap.h>
#include <MenuItem.h>
#define MENUITEM_ICON_SIZE 16
class MethodMenuItem : public BMenuItem {
public:
MethodMenuItem(int32 cookie, const char *label, const uchar *icon, BMenu *subMenu, BMessenger &messenger);
MethodMenuItem(int32 cookie, const char *label, const uchar *icon);
virtual ~MethodMenuItem();
//virtual void Draw();
virtual void DrawContent();
virtual void GetContentSize(float *width, float *height);
void SetName(const char *name);
const char *Name() { return Label(); };
void SetIcon(const uchar *icon);
const uchar *Icon() { return (uchar *)fIcon.Bits(); };
const int32 Cookie() { return fCookie; };
private:
BBitmap fIcon;
int32 fCookie;
BMessenger fMessenger;
};
#endif

View File

@ -0,0 +1,334 @@
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
// Copyright (c) 2004, Haiku
//
// This software is part of the Haiku distribution and is covered
// by the Haiku license.
//
//
// File: MethodReplicant.cpp
// Authors: Jérôme Duval,
//
// Description: Input Server
// Created: October 13, 2004
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#include <Alert.h>
#include <AppDefs.h>
#include <Debug.h>
#include <Dragger.h>
#include <Bitmap.h>
#include <MenuItem.h>
#include <Message.h>
#include <Messenger.h>
#include <PopUpMenu.h>
#include <string.h>
#include "MethodReplicant.h"
#include "remote_icon.h"
#include "InputServerTypes.h"
#ifdef DEBUG
#define CALLED() PRINT(("CALLED %s \n", __PRETTY_FUNCTION__));
#else
#define CALLED()
#endif
MethodReplicant::MethodReplicant(const char* signature)
: BView(BRect(0, 0, 15, 15), REPLICANT_CTL_NAME, B_FOLLOW_ALL, B_WILL_DRAW),
fMenu("", false, false)
{
// Background Bitmap
fSegments = new BBitmap(BRect(0, 0, kRemoteWidth - 1, kRemoteHeight - 1), kRemoteColorSpace);
fSegments->SetBits(kRemoteBits, kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace);
// Background Color
SetViewColor(184,184,184);
//add dragger
BRect rect(Bounds());
rect.left = rect.right-7.0;
rect.top = rect.bottom-7.0;
BDragger *dragger = new BDragger(rect, this, B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
AddChild(dragger);
dragger->SetViewColor(B_TRANSPARENT_32_BIT);
ASSERT(signature!=NULL);
fSignature = strdup(signature);
fMenu.SetFont(be_plain_font);
fMenu.SetRadioMode(true);
}
MethodReplicant::MethodReplicant(BMessage *message)
: BView(message),
fMenu("", false, false)
{
// Background Bitmap
fSegments = new BBitmap(BRect(0, 0, kRemoteWidth - 1, kRemoteHeight - 1), kRemoteColorSpace);
fSegments->SetBits(kRemoteBits, kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace);
const char *signature = NULL;
message->FindString("add_on", &signature);
ASSERT(signature!=NULL);
fSignature = strdup(signature);
fMenu.SetFont(be_plain_font);
fMenu.SetRadioMode(true);
}
MethodReplicant::~MethodReplicant()
{
delete fSegments;
delete fSignature;
}
// archiving overrides
MethodReplicant *
MethodReplicant::Instantiate(BMessage *data)
{
if (!validate_instantiation(data, REPLICANT_CTL_NAME))
return NULL;
return new MethodReplicant(data);
}
status_t
MethodReplicant::Archive(BMessage *data, bool deep) const
{
BView::Archive(data, deep);
data->AddString("add_on", fSignature);
return B_NO_ERROR;
}
void
MethodReplicant::AttachedToWindow()
{
BMessenger messenger(this);
BMessage msg(IS_METHOD_REGISTER);
msg.AddMessenger("address", messenger);
BMessenger inputMessenger("application/x-vnd.Be-input_server");
BMessage reply;
if (inputMessenger.SendMessage(&msg, &reply)!=B_OK) {
printf("error when contacting input_server\n");
}
PRINT_OBJECT(reply);
}
void
MethodReplicant::MessageReceived(BMessage *message)
{
PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what>>24, message->what>>16, message->what>>8, message->what));
PRINT_OBJECT(*message);
switch (message->what) {
case B_ABOUT_REQUESTED:
(new BAlert("About Method Replicant", "Method Replicant (Replicant)\n"
" Brought to you by Jérôme DUVAL.\n\n"
"Haiku, 2004","OK"))->Go();
break;
case IS_UPDATE_NAME:
UpdateMethodName(message);
break;
case IS_UPDATE_ICON:
UpdateMethodIcon(message);
break;
case IS_UPDATE_MENU:
UpdateMethodMenu(message);
break;
case IS_UPDATE_METHOD:
UpdateMethod(message);
break;
default:
BView::MessageReceived(message);
break;
}
}
void
MethodReplicant::Draw(BRect rect)
{
BView::Draw(rect);
SetDrawingMode(B_OP_OVER);
DrawBitmap(fSegments);
}
void
MethodReplicant::MouseDown(BPoint point)
{
CALLED();
uint32 mouseButtons;
BPoint where;
GetMouse(&where, &mouseButtons, true);
where = ConvertToScreen(point);
BMenuItem *tmpItem;
fMenu.AddItem(tmpItem = new MethodMenuItem(0, "Roman", kRemoteBits));
BMenu *otherMenu = new BMenu("Help");
otherMenu->AddItem(new BMenuItem("Help", NULL));
BMessenger messenger;
fMenu.AddItem(new MethodMenuItem(0x80029138, "Roman Roman", kRemoteBits, otherMenu, messenger));
tmpItem->SetMarked(true);
fMenu.SetTargetForItems(this);
MethodMenuItem *item = (MethodMenuItem*)fMenu.Go(where, true, true, BRect(where - BPoint(4, 4),
where + BPoint(4, 4)));
if (item) {
BMessage msg(IS_SET_METHOD);
msg.AddInt32("cookie", item->Cookie());
BMessenger messenger("application/x-vnd.Be-input_server");
messenger.SendMessage(&msg);
}
}
void
MethodReplicant::MouseUp(BPoint point)
{
/* don't Quit() ! thanks for FFM users */
}
void
MethodReplicant::UpdateMethod(BMessage *message)
{
CALLED();
int32 cookie;
if (message->FindInt32("cookie", &cookie)!=B_OK) {
fprintf(stderr, "can't find cookie in message\n");
return;
}
MethodMenuItem *item = FindItemByCookie(cookie);
if (item == NULL) {
fprintf(stderr, "can't find item with cookie %lx\n", cookie);
return;
}
item->SetMarked(true);
}
void
MethodReplicant::UpdateMethodIcon(BMessage *message)
{
CALLED();
int32 cookie;
if (message->FindInt32("cookie", &cookie)!=B_OK) {
fprintf(stderr, "can't find cookie in message\n");
return;
}
const uchar *data;
ssize_t numBytes;
if (message->FindData("icon", B_ANY_TYPE, (const void**)&data, &numBytes)!=B_OK) {
fprintf(stderr, "can't find icon in message\n");
return;
}
MethodMenuItem *item = FindItemByCookie(cookie);
if (item == NULL) {
fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie);
return;
}
item->SetIcon(data);
}
void
MethodReplicant::UpdateMethodMenu(BMessage *message)
{
CALLED();
int32 cookie;
if (message->FindInt32("cookie", &cookie)!=B_OK) {
fprintf(stderr, "can't find cookie in message\n");
return;
}
BMessage msg;
if (message->FindMessage("menu", &msg)!=B_OK) {
fprintf(stderr, "can't find menu in message\n");
return;
}
PRINT_OBJECT(msg);
BMessenger messenger;
if (message->FindMessenger("target", &messenger)!=B_OK) {
fprintf(stderr, "can't find target in message\n");
return;
}
BMenu *menu = (BMenu *)BMenu::Instantiate(&msg);
if (menu == NULL) {
fprintf(stderr, "can't instantiate menu\n");
return;
}
menu->SetTargetForItems(messenger);
MethodMenuItem *item = FindItemByCookie(cookie);
if (item == NULL) {
fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie);
return;
}
int32 index = fMenu.IndexOf(item);
MethodMenuItem *item2 = new MethodMenuItem(cookie, item->Label(), item->Icon(),
menu, messenger);
fMenu.RemoveItem(index);
fMenu.AddItem(item2, index);
}
void
MethodReplicant::UpdateMethodName(BMessage *message)
{
CALLED();
int32 cookie;
if (message->FindInt32("cookie", &cookie)!=B_OK) {
fprintf(stderr, "can't find cookie in message\n");
return;
}
const char *name;
if (message->FindString("name", &name)!=B_OK) {
fprintf(stderr, "can't find name in message\n");
return;
}
MethodMenuItem *item = FindItemByCookie(cookie);
if (item == NULL) {
fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie);
return;
}
item->SetName(name);
}
MethodMenuItem *
MethodReplicant::FindItemByCookie(int32 cookie)
{
for (int32 i=0; i<fMenu.CountItems(); i++) {
MethodMenuItem *item = (MethodMenuItem *)fMenu.ItemAt(i);
PRINT(("cookie : 0x%lx\n", item->Cookie()));
if (item->Cookie()==cookie)
return item;
}
return NULL;
}

View File

@ -0,0 +1,62 @@
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
// Copyright (c) 2004, Haiku
//
// This software is part of the Haiku distribution and is covered
// by the Haiku license.
//
//
// File: MethodReplicant.h
// Authors: Jérôme Duval,
//
// Description: Input Server
// Created: October 13, 2004
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#ifndef METHOD_REPLICANT_H_
#define METHOD_REPLICANT_H_
#include <PopUpMenu.h>
#include <View.h>
#include "MethodMenuItem.h"
#define REPLICANT_CTL_NAME "MethodReplicant"
class _EXPORT MethodReplicant;
class MethodReplicant : public BView {
public:
MethodReplicant(const char* signature);
MethodReplicant(BMessage *);
// BMessage * based constructor needed to support archiving
virtual ~MethodReplicant();
// archiving overrides
static MethodReplicant *Instantiate(BMessage *data);
virtual status_t Archive(BMessage *data, bool deep = true) const;
virtual void AttachedToWindow();
// misc BView overrides
virtual void MouseDown(BPoint);
virtual void MouseUp(BPoint);
virtual void Draw(BRect );
virtual void MessageReceived(BMessage *);
private:
BBitmap *fSegments;
char *fSignature;
BPopUpMenu fMenu;
void UpdateMethod(BMessage *);
void UpdateMethodIcon(BMessage *);
void UpdateMethodMenu(BMessage *);
void UpdateMethodName(BMessage *);
MethodMenuItem *FindItemByCookie(int32 cookie);
};
#endif

View File

@ -0,0 +1,23 @@
const int32 kRemoteWidth = 16;
const int32 kRemoteHeight = 16;
const color_space kRemoteColorSpace = B_CMAP8;
const unsigned char kRemoteBits [] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0x0b,0xff,0xff,0x18,0x00,0x00,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0x00,0xff,0x0b,0xff,0x0b,0xff,0x0b,0xff,0xff,0x00,0x00,
0xff,0xff,0xff,0xff,0x00,0xff,0x0b,0xff,0x0b,0xff,0x0b,0xff,0xff,0x0a,0x0b,0x00,
0xff,0xff,0xff,0x00,0xff,0x0b,0xff,0x0b,0xff,0x0b,0xff,0xff,0x0a,0x0a,0x00,0x0f,
0xff,0xff,0x00,0xff,0x0b,0xff,0x0b,0xff,0x0b,0xff,0xff,0x0b,0x0a,0x00,0x0f,0x0f,
0xff,0x00,0xff,0x0b,0xff,0x0b,0xff,0x0b,0xff,0xff,0x0b,0x0a,0x00,0x0f,0x0f,0xff,
0x00,0xff,0xff,0xff,0x0a,0x18,0x0b,0xff,0xff,0x0a,0x0b,0x00,0x0f,0x0f,0xff,0xff,
0x00,0x11,0x11,0xff,0xff,0x0b,0xff,0xff,0x0a,0x0a,0x00,0x0f,0x0f,0xff,0xff,0xff,
0x00,0x11,0x11,0x11,0x11,0xff,0xff,0x0b,0x0a,0x00,0x0f,0x0f,0xff,0xff,0xff,0xff,
0xff,0x00,0x00,0x11,0x11,0x11,0x0b,0x0b,0x00,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x11,0x0b,0x00,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};