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 <MessageRunner.h>
21#include <Region.h>
22#include <Screen.h>
23
24#if DEBUG
25//#include <File.h>
26#include <Alert.h>
27#include <Button.h>
28#include <TextView.h>
29#include <StringIO.h>
30#include "DumpMessage.h"
31#endif
32
33#include "PenInputLooper.h"
34#include "PenInputBackend.h"
35#include "PenInputInkWindow.h"
36#include "PenInputServerMethod.h"
37#include "PenInputStrings.h"
38
39PenInputLooper::PenInputLooper(PenInputServerMethod *method)
40	: BLooper("PenInputLooper", B_NORMAL_PRIORITY),
41	  fOwner(method),
42	  fInkWindow(NULL),
43	  fBackend(NULL),
44	  fDeskbarMenu(NULL),
45	  fMouseDown(false),
46	  fStroking(false),
47	  fThresholdRunner(NULL),
48	  fCachedMouseDown(NULL),
49	  fShowInk(true),
50	  fMouseDownThreshold(100000)
51{
52	PRINT(("%s\n", __FUNCTION__));
53
54	//
55	fDeskbarMenu = new BMenu(_T("Options"));
56	BMenu *subMenu;
57
58
59	subMenu = new BMenu(_T("Backend"));
60
61	BMessage *msg;
62	msg = new BMessage(MSG_SET_BACKEND);
63	BMenuItem *item;
64	// for (i = 0; i < fBackends.CountItems(); i++) ...
65	item = new BMenuItem(_T("Default"), msg);
66	item->SetMarked(true);
67	subMenu->AddItem(item);
68
69	item = new BMenuItem(subMenu);
70	fDeskbarMenu->AddItem(item);
71
72	msg = new BMessage(MSG_SHOW_INK);
73	item = new BMenuItem(_T("Show Ink"), msg);
74	item->SetMarked(true);
75	fDeskbarMenu->AddItem(item);
76
77	fDeskbarMenu->SetFont(be_plain_font);
78	fOwner->SetMenu(fDeskbarMenu, BMessenger(NULL, this));
79
80#if 0
81	BRegion region;
82	fOwner->GetScreenRegion(&region);
83	fInkWindow = new PenInputInkWindow(region.Frame());
84#endif
85	BScreen screen;
86	fInkWindow = new PenInputInkWindow(screen.Frame());
87	fInkWindow->Show();
88	fInkWindow->Lock();
89	fInkWindow->Hide();
90	fInkWindow->Unlock();
91	fInkWindowMsgr = BMessenger(NULL, fInkWindow);
92
93	BMessage m(MSG_CHECK_PEN_DOWN);
94	fThresholdRunner = new BMessageRunner(BMessenger(NULL, this), &m, fMouseDownThreshold, 0);
95
96	Run();
97}
98
99void PenInputLooper::Quit()
100{
101	PRINT(("%s\n", __FUNCTION__));
102	delete fThresholdRunner;
103	fInkWindow->Lock();
104	fInkWindow->Quit();
105	fOwner->SetMenu(NULL, BMessenger());
106	delete fDeskbarMenu;
107	BLooper::Quit();
108}
109
110
111void PenInputLooper::DispatchMessage(BMessage *message, BHandler *handler)
112{
113	switch (message->what) {
114#if 0
115	case B_MOUSE_MOVED:
116	case B_MOUSE_DOWN:
117	case B_MOUSE_UP:
118
119	case B_INPUT_METHOD_EVENT:
120		//case B_REPLY:
121		if (fBackend) {
122			fBackend->MessageReceived(message);
123			return;
124		}
125#endif
126	default:
127		return BLooper::DispatchMessage(message, handler);
128	}
129}
130
131void PenInputLooper::MessageReceived(BMessage *message)
132{
133	int32 v;
134	int32 buttons;
135	bool b;
136#if 1
137    {
138		//message->Flatten(&fDebugFile);
139		BStringIO sio;
140		DumpMessageToStream(message, sio);
141		fInkWindow->Lock();
142		sio << BString("StrokesCount: ");
143		BString tmp;
144		tmp << fInkWindow->fStrokeCount;
145		sio << tmp;
146		sio << BString("\nStrokes.Bounds: ");
147		sio << (fInkWindow->fStrokes.Bounds());
148		sio << BString("\n");
149		fInkWindow->Unlock();
150		fOwner->fDebugAlert->Lock();
151		fOwner->fDebugAlert->TextView()->Insert("Looper:\n");
152		fOwner->fDebugAlert->TextView()->Insert(sio.String());
153		fOwner->fDebugAlert->Unlock();
154    }
155#endif
156	switch (message->what) {
157	case MSG_CHECK_PEN_DOWN:
158		if (fCachedMouseDown) {
159			/* nothing happened, we want to move the mouse */
160			EnqueueMessage(fCachedMouseDown);
161			fCachedMouseDown = NULL;
162		}
163		break;
164	case B_MOUSE_MOVED:
165		if (!fMouseDown) { /* definitely not writing */
166			/* pass it along */
167			EnqueueMessage(DetachCurrentMessage());
168			break;
169		}
170		if (fShowInk) {
171			BMessage *msg = new BMessage(*message);
172			fInkWindowMsgr.SendMessage(msg);
173		}
174		if (fBackend)
175			fBackend->MessageReceived(message);
176		else
177			EnqueueMessage(DetachCurrentMessage());
178		break;
179	case B_MOUSE_DOWN:
180		if (message->FindInt32("buttons", &buttons) == B_OK) {
181			if (!(buttons & B_PRIMARY_MOUSE_BUTTON)) {
182				/* pass it along */
183				EnqueueMessage(DetachCurrentMessage());
184				break;
185			}
186		}
187		fMouseDown = true;
188		if (fShowInk) {
189			{
190				BMessage *msg = new BMessage(MSG_BEGIN_INK);
191				fInkWindowMsgr.SendMessage(msg);
192			}
193			BMessage *msg = new BMessage(*message);
194			fInkWindowMsgr.SendMessage(msg);
195		}
196		if (fBackend)
197			fBackend->MessageReceived(message);
198		break;
199	case B_MOUSE_UP:
200		if (message->FindInt32("buttons", &buttons) == B_OK) {
201			if (!fMouseDown || (buttons & B_PRIMARY_MOUSE_BUTTON)) {
202				/* pass it along */
203				EnqueueMessage(DetachCurrentMessage());
204				break;
205			}
206		}
207		fMouseDown = false;
208		if (fShowInk) {
209			BMessage *msg = new BMessage(*message);
210			fInkWindowMsgr.SendMessage(msg);
211			{
212				BMessage *msg = new BMessage(MSG_END_INK);
213				fInkWindowMsgr.SendMessage(msg);
214			}
215		}
216		if (fBackend)
217			fBackend->MessageReceived(message);
218		break;
219	case B_INPUT_METHOD_EVENT:
220		if (fBackend)
221			fBackend->MessageReceived(message);
222		break;
223	case MSG_METHOD_ACTIVATED:
224		if (message->FindBool(MSGF_ACTIVE, &b) < B_OK)
225			b = false;
226		HandleMethodActivated(b);
227		break;
228	case B_REPLY:
229
230	default:
231		BLooper::MessageReceived(message);
232		break;
233	}
234}
235
236void PenInputLooper::EnqueueMessage(BMessage *message)
237{
238	fOwner->EnqueueMessage(message);
239}
240
241status_t PenInputLooper::InitCheck()
242{
243	return B_OK;
244}
245
246void PenInputLooper::HandleMethodActivated(bool active)
247{
248/*
249  if (fShowInk && active)
250  fInkWindowMsgr.SendMessage(MSG_SHOW_WIN);
251  if (fShowInk && !active)
252  fInkWindowMsgr.SendMessage(MSG_END_INK);
253*/
254}
255
256