1/*
2	Copyright 2007, Francois Revol.   All Rights Reserved.
3	This file may be used under the terms of the Be Sample Code License.
4*/
5
6//#define DEBUG 1
7
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11
12#include <Debug.h>
13#include <List.h>
14#include <Message.h>
15#include <OS.h>
16
17#include <Application.h>
18#include <Menu.h>
19#include <MenuItem.h>
20#include <Region.h>
21
22#if DEBUG
23//#include <File.h>
24#include <Alert.h>
25#include <Button.h>
26#include <TextView.h>
27#include <StringIO.h>
28#include "DumpMessage.h"
29#endif
30
31#include <add-ons/input_server/InputServerDevice.h>
32#include <add-ons/input_server/InputServerMethod.h>
33
34#include "PenIcon.h"
35
36#include "PenInputServerMethod.h"
37#include "PenInputLooper.h"
38#include "PenInputStrings.h"
39
40BInputServerMethod* instantiate_input_method()
41{
42	PRINT(("%s\n", __FUNCTION__));
43	return (new PenInputServerMethod());
44}
45
46
47PenInputServerMethod::PenInputServerMethod()
48  : BInputServerMethod("Pen", PenIconData),
49    fEnabled(false)
50{
51	PRINT(("%s\n", __FUNCTION__));
52#if DEBUG
53	//fDebugFile.SetTo("/tmp/PenInputMethodMessages.txt", B_READ_WRITE|B_CREATE_FILE);
54	fDebugAlert = new BAlert("PenInput Debug", "Plip                                   \n\n\n\n\n\n\n\n\n\n\n\n\n", "OK");
55	fDebugAlert->SetLook(B_TITLED_WINDOW_LOOK);
56	fDebugAlert->SetFlags(fDebugAlert->Flags() | B_CLOSE_ON_ESCAPE);
57	fDebugAlert->TextView()->MakeSelectable();
58	fDebugAlert->TextView()->SelectAll();
59	fDebugAlert->TextView()->Delete();
60	fDebugAlert->ButtonAt(0)->SetEnabled(false);
61	BRegion r;
62	GetScreenRegion(&r);
63	BString s;
64	s << r.CountRects() << " rects\n";
65	fDebugAlert->TextView()->Insert(s.String());
66	fDebugAlert->Go(NULL);
67
68
69#endif
70}
71
72PenInputServerMethod::~PenInputServerMethod()
73{
74	PRINT(("%s\n", __FUNCTION__));
75	SetMenu(NULL, BMessenger());
76#if DEBUG
77	fDebugAlert->Lock();
78	fDebugAlert->Quit();
79#endif
80	BLooper *looper = NULL;
81	fLooper.Target(&looper);
82	if (looper != NULL)
83	{
84		if (looper->Lock())
85			looper->Quit();
86	}
87}
88
89status_t PenInputServerMethod::InitCheck()
90{
91	PenInputLooper *looper;
92	status_t err;
93	PRINT(("%s\n", __FUNCTION__));
94	looper = new PenInputLooper(this);
95	looper->Lock();
96	err = looper->InitCheck();
97	looper->Unlock();
98	fLooper = BMessenger(NULL, looper);
99	return err;
100}
101
102
103filter_result PenInputServerMethod::Filter(BMessage *message, BList *outList)
104{
105	status_t err;
106	filter_result res = B_DISPATCH_MESSAGE;
107
108	if (!IsEnabled())
109		return B_DISPATCH_MESSAGE;
110
111
112#if 0//DEBUG
113	//message->Flatten(&fDebugFile);
114	BStringIO sio;
115	DumpMessageToStream(message, sio);
116	fDebugAlert->Lock();
117	fDebugAlert->TextView()->Insert(sio.String());
118	fDebugAlert->Unlock();
119#endif
120	switch (message->what) {
121	case B_KEY_UP:
122	case B_KEY_DOWN:
123	case B_UNMAPPED_KEY_UP:
124	case B_UNMAPPED_KEY_DOWN:
125	case B_MODIFIERS_CHANGED:
126	case B_MOUSE_WHEEL_CHANGED:
127		return B_DISPATCH_MESSAGE;
128	default:
129		//case B_MOUSE_MOVED:
130		fLooper.SendMessage(message);
131		return B_SKIP_MESSAGE;
132	}
133
134
135#if 0
136	if (message->what == B_MOUSE_MOVED) {
137	  BMessage *mDown = new BMessage(B_KEY_DOWN);
138	  BMessage *mUp;
139	  char states[16];
140	  mDown->AddInt32("modifiers", 0x0);
141	  mDown->AddInt32("key", 94);
142	  mDown->AddInt32("raw_char", 32);
143	  mDown->AddData("states", 'UBYT', states, sizeof(states));
144	  mDown->AddString("bytes", " ");
145	  mDown->AddData("byte", 'BYTE', " ", 1);
146	  mUp = new BMessage(*mDown);
147	  mUp->what = B_KEY_UP;
148	  outList->AddItem(mDown);
149	  outList->AddItem(mUp);
150	}
151#endif
152	if (message->what == B_MOUSE_DOWN) {
153	  int32 buttons;
154	  int32 modifiers;
155	  BPoint where;
156	  if (message->FindInt32("buttons", &buttons) == B_OK) {
157	    /* replace first with a button that likely won't exist,
158	     * and so shouldn't cause any side effect (hmm err...) */
159	    /* XXX: use get_mouse_map() ? */
160	    if (buttons == B_PRIMARY_MOUSE_BUTTON)
161	      //message->ReplaceInt32("buttons", 0x0000);
162	      message->what = B_MOUSE_UP;
163	  }
164
165#if 0
166	  outList->AddItem(new BMessage(*message));
167	  BMessage *m = new BMessage(B_MOUSE_MOVED);
168	  if (message->FindInt32("buttons", &buttons) == B_OK)
169	    m->AddInt32("buttons", buttons);
170	  if (message->FindInt32("modifiers", &modifiers) == B_OK)
171	    m->AddInt32("modifiers", modifiers);
172	  if (message->FindPoint("where", &where) == B_OK)
173	    m->AddPoint("where", where);
174	  outList->AddItem(m);
175#endif
176#if DEBUG
177	  fDebugAlert->Lock();
178	  fDebugAlert->TextView()->Insert(">>>\n");
179	  fDebugAlert->Unlock();
180#endif
181#if 0
182	  m = new BMessage(B_INPUT_METHOD_EVENT);
183	  m->AddInt32("be:opcode", B_INPUT_METHOD_STARTED);
184	  m->AddMessenger("be:reply_to", this);
185	  EnqueueMessage(m);
186	  m = new BMessage(B_INPUT_METHOD_EVENT);
187	  m->AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
188	  m->AddString("be:string", " ");
189	  EnqueueMessage(m);
190	  m = new BMessage(B_INPUT_METHOD_EVENT);
191	  m->AddInt32("be:opcode", B_INPUT_METHOD_STOPPED);
192	  EnqueueMessage(m);
193	  sleep(3);
194#endif
195#if DEBUG
196	  fDebugAlert->Lock();
197	  fDebugAlert->TextView()->Insert("<<<\n");
198	  fDebugAlert->Unlock();
199#endif
200	}
201
202
203
204	return (res);
205}
206
207status_t PenInputServerMethod::MethodActivated(bool active)
208{
209	fEnabled = active;
210
211	BMessage msg(MSG_METHOD_ACTIVATED);
212	if (active)
213		msg.AddBool(MSGF_ACTIVE, true);
214	fLooper.SendMessage( &msg );
215
216	return B_OK;
217}
218
219