Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Developing U++ » U++ Developers corner » Using Pen with U++
Re: Using Pen with U++ [message #56548 is a reply to message #56547] Wed, 24 March 2021 15:21 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
OK, I see. I'll give it a try... (will return soon.)

Best regards,

Tom
Re: Using Pen with U++ [message #56549 is a reply to message #56548] Wed, 24 March 2021 15:56 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Tom1 wrote on Wed, 24 March 2021 15:21
OK, I see. I'll give it a try... (will return soon.)

Best regards,

Tom


Well, I thought I will do that tonight or tomorrow, but if you want to try, there are some tips and tricks how I planned to do it:

- add another kind of event PEN 0xf0 after TRIPLE constant
- will need to add handling in DoMouse around CtrlCore/CtrlMouse.cpp:149
- we will need to somehow return that bool; DoMouse returns Image, here I planned to use a trick to return Null or Non-null image to signal true-falase (use any image available)
- as for Pen signature, I was thinking about creating some struct type with all the information (pressure, tilt etc) that would be passed as parameter. Perhaps leave Point as separate parameter. So something like

virtual bool Pen(Point p, const PenInfo& f);

Mirek
Re: Using Pen with U++ [message #56550 is a reply to message #56549] Wed, 24 March 2021 16:51 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Mirek,

I was only thinking about declaring:
	virtual bool   PenDown(Point p, dword keyflags){ return false; }
	virtual bool   PenUp(Point p, dword keyflags){ return false; }
	virtual bool   PenMove(Point p, dword keyflags){ return false; }

and calling them directly like this
				switch(message) {
				case WM_POINTERDOWN:
					ClickActivateWnd();
					if(PenDown(Point(p), GetMouseFlags())) return 0L;
					break;
				case WM_POINTERUP:
					if(PenUp(Point(p), GetMouseFlags())) return 0L;
					break;
				case WM_POINTERUPDATE:
					if(PenMove(Point(p), GetMouseFlags())) return 0L;
					break;
				}
				break;

...and using the Pen -functions you made earlier.

However, my simple approach above would inevitably have its shortcomings as properly tracking the pen/mouse position (e.g. GetMousePos()) cannot be taken care of this way. RectTracker would likely also be broken in this case.

Despite working several tens of hours on this, my understanding on Ctrl and mouse processing is not sufficient yet to do it the right way. (Despite the several tens of hours I have spent on this during the few last days. Shame on me.)

So, absolutely, if you have time, please do it the right way. (I have a strong feeling that it will eventually save time for both of us.)

In any case, I'll be here ready to test as soon as you post an update.

Best regards,

Tom

EDIT: BTW: How did you think about handling barrel-button and other flags? After playing around with the pen, I have noticed that it is very difficult to click barrel and other buttons on the pen while keeping it steady. So, IMO, barrel should be just a flag to read when pen goes down/up or moves. Just like Shift/Ctrl/Alt, which are used and needed as modifiers similarly for pen and mouse.

Also, I feel PenMove + PenDown + PenUp make it easier to write code for the pen, instead of a single PenUpdate function.

Further on, readily supporting PenHold, PenDouble (and possibly PenTriple) would be useful. Decoding them in application would require passing timestamps too, which is not very convenient.

EDIT2: Actually, I would rather have PEN defined as 3 or 4, i.e. in parallel to LEFT, RIGHT and MIDDLE. This way we can have PEN|DOWN, PEN|UP, PEN|DOUBLE, ... and just PEN for move.

[Updated on: Wed, 24 March 2021 17:27]

Report message to a moderator

Re: Using Pen with U++ [message #56551 is a reply to message #56550] Wed, 24 March 2021 18:01 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Tom1 wrote on Wed, 24 March 2021 16:51
Mirek,

I was only thinking about declaring:
	virtual bool   PenDown(Point p, dword keyflags){ return false; }
	virtual bool   PenUp(Point p, dword keyflags){ return false; }
	virtual bool   PenMove(Point p, dword keyflags){ return false; }

and calling them directly like this
				switch(message) {
				case WM_POINTERDOWN:
					ClickActivateWnd();
					if(PenDown(Point(p), GetMouseFlags())) return 0L;
					break;
				case WM_POINTERUP:
					if(PenUp(Point(p), GetMouseFlags())) return 0L;
					break;
				case WM_POINTERUPDATE:
					if(PenMove(Point(p), GetMouseFlags())) return 0L;
					break;
				}
				break;

...and using the Pen -functions you made earlier.


This would not work - only top level windows are receiving messages from Win32. DoMouse then distributes them to target widgets (with a ton of logic and coordinate translations involved).

Quote:

EDIT: BTW: How did you think about handling barrel-button and other flags? After playing around with the pen, I have noticed that it is very difficult to click barrel and other buttons on the pen while keeping it steady. So, IMO, barrel should be just a flag to read when pen goes down/up or moves. Just like Shift/Ctrl/Alt, which are used and needed as modifiers similarly for pen and mouse.


As flag in PenInfo. That is the reason I vote for structure passed so that it can be extended.

Quote:

Also, I feel PenMove + PenDown + PenUp make it easier to write code for the pen, instead of a single PenUpdate function.


IDK. I feel like pen actually would be better handled with single method. I guess I have to try.

Mirek
Re: Using Pen with U++ [message #56552 is a reply to message #56551] Wed, 24 March 2021 18:22 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
OK. PenInfo structure sounds good.

Please include 'dword keyflags' in call parameters or PenInfo.

Also, if you end up with a single method like 'PenUpdate()' or whatever, please also include reason = MOVE/DOWN/UP/HOLD/DOUBLE/... in call parameters or PenInfo.

Thanks and best regards,

Tom
Re: Using Pen with U++ [message #56564 is a reply to message #56552] Thu, 25 March 2021 19:58 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
First attempt commited.

#include <CtrlLib/CtrlLib.h>

using namespace Upp;

struct MyApp : TopWindow {
	Point pos;
	
	Vector<Vector<Tuple<double, Pointf>>> drawing;

	PenInfo pen;
	
	virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
		if(pn.pressure) {
			if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
				drawing.Top().Add(MakeTuple(pn.pressure, p));
			else
				drawing.Add().Add(MakeTuple(pn.pressure, p));
		}
		pen = pn;
		Refresh();
		return true;
	}
	
	virtual void Paint(Draw& w0) {
		DrawPainter w(w0, GetSize());
		w.Co();
		w.Clear(SColorPaper());
		
		w.LineCap(LINECAP_ROUND);
		for(const auto& stroke : drawing)
			if(stroke.GetCount())
				for(int i = 0; i < stroke.GetCount() - 1; i++) {
					w.Move(stroke[i].b);
					w.Line(stroke[i + 1].b);
					w.Stroke(DPI(20) * stroke[i].a, Black());
				}
		
		int fcy = GetStdFontCy();
		int y = 10;
		auto Text = [&] (const String& text) {
			w.DrawText(10, y, text);
			y += fcy;
		};
		Text(AsString(pos));
		Text(String() << "Pressure: " << pen.pressure);
		Text(String() << "Rotation: " << pen.rotation);
		Text(String() << "Tilt: " << pen.tilt);
		Text(String() << "Barrel: " << pen.barrel);
		Text(String() << "Inverted: " << pen.inverted);
		Text(String() << "Eraser: " << pen.eraser);
	}
};

GUI_APP_MAIN
{
	MyApp().Run();
}
Re: Using Pen with U++ [message #56565 is a reply to message #56564] Thu, 25 March 2021 20:47 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi Mirek,

And thanks for the first round on the new Pen interface. Smile

The standard controls seem to work correctly (as expected) and the new interface is nice and clean.

However, the RectTracker needs attention. Please add the following code to the test case and see what happens with Ctrl+Pen and Shift+Pen:

	virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
		if(pn.action==PEN_DOWN){
			if(keyflags&K_SHIFT){
				RectTracker tracker(*this);
				tracker.sync= [=](Rect r) {  };
				tracker.MinSize(Size(-100000,-100000));
				tracker.Track(Rect(p,p));
			}
			else if(keyflags&K_CTRL){
				RectTracker tracker(*this);
				tracker.TrackLine(p.x,p.y);
			}
		}
		
		if(pn.pressure) {
			if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
				drawing.Top().Add(MakeTuple(pn.pressure, p));
			else
				drawing.Add().Add(MakeTuple(pn.pressure, p));
		}
		pen = pn;
		Refresh();
		return true;
	}


Thanks and best regards,

Tom
Re: Using Pen with U++ [message #56567 is a reply to message #56565] Thu, 25 March 2021 22:07 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, I will try to make it work, however the indended road was something like

	virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
		if(keyflags&K_SHIFT)
			return false;
		if(pn.pressure) {
			if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
				drawing.Top().Add(MakeTuple(pn.pressure, p));
			else
				drawing.Add().Add(MakeTuple(pn.pressure, p));
		}
		pen = pn;
		Refresh();
		return true;
	}
	
	void LeftDown(Point p, dword keyflags) override {
		if(keyflags & K_SHIFT) {
			RectTracker tracker(*this);
			tracker.MinSize(Size(-100000,-100000));
			tracker.Track(Rect(p,p));
		}
	}
Re: Using Pen with U++ [message #56568 is a reply to message #56565] Thu, 25 March 2021 22:28 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Mirek,

Is pn.action intentionally merely a state flag showing continuously PEN_UP or PEN_DOWN? Or should we reset it along with other PenInfo items in the beginning of processing WM_POINTER* messages?

I would like to have it reset, in order to more easily detect UP/DOWN state changes without a state variable and treat zero action as 'PEN_MOVE'.

Then we could do this to decode all kinds of pen events:

#define PENMOVE		0
#define PENDOWN		1
#define PENUP		2
#define PENHOLD		3
#define PENDRAG		4
#define PENDOUBLE	5
#define PENTRIPLE	6

bool IsNear(Point p, Point o){
	Point delta(p-o);
	if(abs(delta.x)<5 && abs(delta.y)<5) return true;
	return false;
}
	
int PenDecoder(Point p, const PenInfo& pn, dword keyflags){
	static int action=0;
	static int downt=0;
	static Point downp=Null;
	static bool doubleClick=true;
	static bool down=false;
	static bool solved=false;
	int now=msecs();
	int deltat=now-downt;
	
	
	bool isNear=IsNear(p,downp);
	
	switch(pn.action){
		case PEN_DOWN:
			down=true;
			solved=false;
			downp=p;
			downt=now;
			if(isNear){
				if(now-downt < 500){
					if(doubleClick){
						return PENTRIPLE;
					}
					else{
						doubleClick=true;
						return PENDOUBLE;
					}
				}
			}
			doubleClick=false;
			return PENDOWN;

		case PEN_UP:
			down=false;
			return PENUP;

		default:
			if(down && !solved){
				if(isNear){
					if(now-downt > 1000){
						solved=true;
						return PENHOLD;
					}
				}
				else{
					solved=true;
					return PENDRAG;
				}
			}
			return PENMOVE;
	}
}


Best regards,

Tom
Re: Using Pen with U++ [message #56569 is a reply to message #56567] Thu, 25 March 2021 22:33 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
mirek wrote on Thu, 25 March 2021 23:07
Well, I will try to make it work, however the indended road was something like

	virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
		if(keyflags&K_SHIFT)
			return false;
		if(pn.pressure) {
			if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
				drawing.Top().Add(MakeTuple(pn.pressure, p));
			else
				drawing.Add().Add(MakeTuple(pn.pressure, p));
		}
		pen = pn;
		Refresh();
		return true;
	}
	
	void LeftDown(Point p, dword keyflags) override {
		if(keyflags & K_SHIFT) {
			RectTracker tracker(*this);
			tracker.MinSize(Size(-100000,-100000));
			tracker.Track(Rect(p,p));
		}
	}


Previous message content cleared.

Issue solved: I will return with a working RectTracker solution in the next message.

Best regards,

Tom

[Updated on: Fri, 26 March 2021 00:15]

Report message to a moderator

Re: Using Pen with U++ [message #56571 is a reply to message #56569] Fri, 26 March 2021 00:22 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
OK, here are all the RectTracker changes required:

Add in RectTracker:: in CtrlCore.h:
	virtual bool  Pen(Point p, const PenInfo& pn, dword keyflags);


Add in LocalLoop.cpp:
bool RectTracker::Pen(Point p, const PenInfo& pn, dword keyflags){
	switch(pn.action){
		default:
			MouseMove(p, keyflags);
			break;
		case PEN_UP:
			LeftUp(p, keyflags);
			break;
	}
	return true;
}

And finally changes in Win32Proc.cpp:
...

static bool pendown=false;

bool GetShift()       { return !!(GetKeyStateSafe(VK_SHIFT) & 0x8000); }
bool GetCtrl()        { return !!(GetKeyStateSafe(VK_CONTROL) & 0x8000); }
bool GetAlt()         { return !!(GetKeyStateSafe(VK_MENU) & 0x8000); }
bool GetCapsLock()    { return !!(GetKeyStateSafe(VK_CAPITAL) & 1); }
bool GetMouseLeft()   { return pendown || !!(GetKeyStateSafe(VK_LBUTTON) & 0x8000); }
bool GetMouseRight()  { return !!(GetKeyStateSafe(VK_RBUTTON) & 0x8000); }
bool GetMouseMiddle() { return !!(GetKeyStateSafe(VK_MBUTTON) & 0x8000); }

bool PassWindowsKey(int wParam);

LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
	GuiLock __;
	eventid++;
//	LLOG("Ctrl::WindowProc(" << message << ") in " << ::Name(this) << ", focus " << (void *)::GetFocus());
	Ptr<Ctrl> _this = this;
	HWND hwnd = GetHWND();

	switch(message) {
	case WM_POINTERDOWN:
	case WM_POINTERUPDATE:
	case WM_POINTERUP: {
			pen.action = 0;
			pen.pressure = pen.rotation = Null;
			pen.tilt = Null;
			pen.eraser = pen.barrel = pen.inverted = pen.history = false;

			static BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
			static BOOL (WINAPI *GetPointerInfo)(UINT32 pointerId, POINTER_INFO *pointerInfo);
			static BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
			static BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32 pointerId, UINT32 *entriesCount, POINTER_PEN_INFO *penInfo);

			ONCELOCK {
				DllFn(GetPointerType, "User32.dll", "GetPointerType");
				DllFn(GetPointerInfo, "User32.dll", "GetPointerInfo");
				DllFn(GetPointerPenInfo, "User32.dll", "GetPointerPenInfo");
				DllFn(GetPointerPenInfoHistory, "User32.dll", "GetPointerPenInfoHistory");
			};

			if(!(GetPointerType && GetPointerInfo && GetPointerPenInfo && GetPointerPenInfoHistory))
				break;

			POINTER_INPUT_TYPE pointerType;

			auto ProcessPenInfo = [&] (POINTER_PEN_INFO& ppi) {
				if(ppi.penFlags & PEN_FLAG_BARREL)
					pen.barrel = true;
				if(ppi.penFlags & PEN_FLAG_INVERTED)
					pen.inverted = true;
				if(ppi.penFlags & PEN_FLAG_ERASER)
					pen.eraser = true;
				if(ppi.penMask & PEN_MASK_PRESSURE)
					pen.pressure = ppi.pressure / 1024.0;
				if(ppi.penMask & PEN_MASK_ROTATION)
					pen.rotation = ppi.rotation * M_2PI / 360;
				if(ppi.penMask & PEN_MASK_TILT_X)
					pen.tilt.x = ppi.tiltX * M_2PI / 360;
				if(ppi.penMask & PEN_MASK_TILT_Y)
					pen.tilt.y = ppi.tiltY * M_2PI / 360;
			};

			UINT32 pointerId = GET_POINTERID_WPARAM(wParam);
			if(GetPointerType(pointerId, &pointerType) && pointerType == PT_PEN) {
				UINT32 hc = 256;
				Buffer<POINTER_PEN_INFO> ppit(hc);
				if(message == WM_POINTERUPDATE && GetPointerPenInfoHistory(pointerId, &hc, ppit)) {
					bool processed = false;
					for(int i = hc - 1; i >= 0; i--) {
						ProcessPenInfo(ppit[i]);
						POINT hp = ppit[i].pointerInfo.ptPixelLocation;
						::SetCursorPos(hp.x,hp.y);
						::ScreenToClient(hwnd, &hp);
						pen.history = (bool)i;
						processed = !IsNull(DoMouse(PEN, hp, 0));
					}
					if(processed)
						return 0L;
					else
						break;
				}
				POINTER_PEN_INFO ppi;
				if(GetPointerPenInfo(pointerId, &ppi))
					ProcessPenInfo(ppi);

				POINT p = ppi.pointerInfo.ptPixelLocation;
				::SetCursorPos(p.x,p.y);
				::ScreenToClient(hwnd, &p);

				switch(message) {
				case WM_POINTERDOWN:
					pendown=true;
					pen.action = PEN_DOWN;
					ClickActivateWnd();
					break;
				case WM_POINTERUP:
					pendown=false;
					pen.action = PEN_UP;
					break;
				}
				if(!IsNull(DoMouse(PEN, p, 0)))
					return 0L;
				break;
			}
		}
		break;
...


The main problem was that ::GetCursorPos() was not working as ::SetCursorPos() was not called from WM_POINTER*. Now it all works and mouse follows pen.

Best regards,

Tom

EDIT: Not quite... calling SetCursorPos() causes incoming WM_MOUSEMOVE messages at some frequency, but the coordinates are obviously old ones causing erratic behavior if both MouseMove and Pen are processed... However, if SetCursorPos() is not called, the mouse position will be different to pen and it will in turn cause flickering RectTracker with intermediate rectangles to mouseposition! Sad

Well, I'm done for today. (or yesterday, or whatever.) Anyway, if you have any ideas how to go around this, please fill in...

[Updated on: Fri, 26 March 2021 01:02]

Report message to a moderator

Re: Using Pen with U++ [message #56573 is a reply to message #56568] Fri, 26 March 2021 08:57 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Tom1 wrote on Thu, 25 March 2021 22:28
Mirek,

Is pn.action intentionally merely a state flag showing continuously PEN_UP or PEN_DOWN? Or should we reset it along with other PenInfo items in the beginning of processing WM_POINTER* messages?

I would like to have it reset, in order to more easily detect UP/DOWN state changes without a state variable and treat zero action as 'PEN_MOVE'.

Then we could do this to decode all kinds of pen events:

#define PENMOVE		0
#define PENDOWN		1
#define PENUP		2
#define PENHOLD		3
#define PENDRAG		4
#define PENDOUBLE	5
#define PENTRIPLE	6

bool IsNear(Point p, Point o){
	Point delta(p-o);
	if(abs(delta.x)<5 && abs(delta.y)<5) return true;
	return false;
}
	
int PenDecoder(Point p, const PenInfo& pn, dword keyflags){
	static int action=0;
	static int downt=0;
	static Point downp=Null;
	static bool doubleClick=true;
	static bool down=false;
	static bool solved=false;
	int now=msecs();
	int deltat=now-downt;
	
	
	bool isNear=IsNear(p,downp);
	
	switch(pn.action){
		case PEN_DOWN:
			down=true;
			solved=false;
			downp=p;
			downt=now;
			if(isNear){
				if(now-downt < 500){
					if(doubleClick){
						return PENTRIPLE;
					}
					else{
						doubleClick=true;
						return PENDOUBLE;
					}
				}
			}
			doubleClick=false;
			return PENDOWN;

		case PEN_UP:
			down=false;
			return PENUP;

		default:
			if(down && !solved){
				if(isNear){
					if(now-downt > 1000){
						solved=true;
						return PENHOLD;
					}
				}
				else{
					solved=true;
					return PENDRAG;
				}
			}
			return PENMOVE;
	}
}


Best regards,

Tom


Would it solve any real problem? I mean, I believe that the application can do all these on its own, if it needs to.
Re: Using Pen with U++ [message #56576 is a reply to message #56573] Fri, 26 March 2021 10:15 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

Well, I put the 'PenDecoder' here just for reference for anyone wishing to map pen to mouse like callbacks in application. It does not really need to be part of CtrlCore.

However, my point here is that, I would feel more at home, if:
- only WM_POINTERUP would cause pn.action=PEN_UP
- only WM_POINTERDOWN would cause pn.action=PEN_DOWN
- and WM_POINTERUPDATE would always keep pn.action=0; (or PEN_MOVE).

I.e. pn.action would be event type instead of state flag of up/down status.

Or do you have some particular reason to always have pn.action set to either PEN_UP or PEN_DOWN depepending on the last change?

Best regards,

Tom
Re: Using Pen with U++ [message #56580 is a reply to message #56576] Fri, 26 March 2021 12:42 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Tom1 wrote on Fri, 26 March 2021 10:15


Or do you have some particular reason to always have pn.action set to either PEN_UP or PEN_DOWN depepending on the last change?

Best regards,

Tom


Ah, sorry, I misunderstood the intent. Nope, that was just a bug, forgot to assign 0 in WindowProc...
Re: Using Pen with U++ [message #56581 is a reply to message #56580] Fri, 26 March 2021 13:39 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Good! Smile

Maybe you can add a:
#define PEN_MOVE 0

or something alike in CtrlCore.h?

Now about that RectTracker: I'm having hard time with the ::GetCursorPos/::SetCursorPos...

::GetCursorPos knows where mouse is, but in order for it to know where Pen is, we would need to call ::SetCursorPos in WM_POINTER*. But calling it results in a slightly delayed WM_MOUSEMOVE message coming in causing all kinds of annoying stuff happening.

If we do not call ::SetCursorPos in WM_POINTER, the Pen and Mouse will be in two different positions causing other issues in many places because ::GetCursorPos only knows about the mouse, not pen.

Any ideas how to proceed?

Best regards,

Tom
Re: Using Pen with U++ [message #56583 is a reply to message #56581] Fri, 26 March 2021 15:05 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1358
Registered: December 2006
Ultimate Contributor
Linux, Clang:
./umk uppsrc ide CLANG -bus
/home/buildbot/worker/l-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:429:6: error: no viable overloaded '='
        pen = CurrentEvent.pen;
        ~~~ ^ ~~~~~~~~~~~~~~~~


Regards,
Novo
Re: Using Pen with U++ [message #56584 is a reply to message #56583] Fri, 26 March 2021 15:08 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1358
Registered: December 2006
Ultimate Contributor
Alpine Linux (in addition to previous error):
./umk uppsrc ide CLANG -bus
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:430:2: error: use of undeclared identifier 'pen_barrel'
        pen_barrel = CurrentEvent.pen_barrel;
        ^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:431:2: error: use of undeclared identifier 'pen_inverted'
        pen_inverted = CurrentEvent.pen_inverted;
        ^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:432:2: error: use of undeclared identifier 'pen_eraser'
        pen_eraser = CurrentEvent.pen_eraser;
        ^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:433:2: error: use of undeclared identifier 'pen_pressure'
        pen_pressure = CurrentEvent.pen_pressure;
        ^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:434:2: error: use of undeclared identifier 'pen_rotation'
        pen_rotation = CurrentEvent.pen_rotation;
        ^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:435:2: error: use of undeclared identifier 'pen_tilt'
        pen_tilt = CurrentEvent.pen_tilt;
        ^


Regards,
Novo
Re: Using Pen with U++ [message #56585 is a reply to message #56581] Fri, 26 March 2021 15:45 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Tom1 wrote on Fri, 26 March 2021 13:39
Good! Smile

Maybe you can add a:
#define PEN_MOVE 0

or something alike in CtrlCore.h?


Is this just MOVE though? I can add PEN_OTHER, but do not see much point. It is UP, DOWN or nothing...

Now about that RectTracker: I'm having hard time with the ::GetCursorPos/::SetCursorPos...

Quote:

If we do not call ::SetCursorPos in WM_POINTER, the Pen and Mouse will be in two different positions causing other issues in many places because ::GetCursorPos only knows about the mouse, not pen.

Any ideas how to proceed?


Well, the whole point of Pen virtual method is that we should not meddle with normal mouse.... Is it so bad to just leave it to LeftDown?

Mirek
Re: Using Pen with U++ [message #56590 is a reply to message #56585] Fri, 26 March 2021 16:44 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Mirek,

'case PEN_OTHER:' Looks better than 'case 0:' ... Smile

Quote:
Is it so bad to just leave it to LeftDown?


I'm not quite sure what do you mean by this.. (?) (If it is about double clicks, drags or barrel mappings to right mouse button, I can handle them in the application side.)

--

Anyway, now the good news: I finally got through with RectTracker and Get/SetCursorPos.

The set of changes required follow.

Add to CtrlCore.h:
bool GetPenDown(); // << ADD THIS
... AND ...
class RectTracker : public LocalLoop {
public:
	virtual void  LeftUp(Point, dword);
	virtual void  RightUp(Point, dword);
	virtual void  MouseMove(Point p, dword);
	virtual bool  Pen(Point p, const PenInfo& pn, dword keyflags); // << ADD THIS

Add "&& !GetPenDown()" at line 595 in CtrlMouse.cpp:
...
	if(findarg(e, LEFTUP, RIGHTUP, MIDDLEUP) >= 0)
		KillRepeat();
	Image result = DispatchMouseEvent(e, p, zd);
	if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft() && !GetPenDown())
		ReleaseCtrlCapture();
	return result;
...

Add to LocalLoop.cpp:
bool RectTracker::Pen(Point p, const PenInfo& pn, dword keyflags){
	switch(pn.action){
		case 0:
			MouseMove(p,keyflags);
			break;
		case PEN_UP:
			EndLoop();
			break;
	}
	return true;
}

Add "&& !GetPenDown()" at line 781 in Win32Wnd.cpp:
...
bool Ctrl::ProcessEvent(bool *quit)
{
	ASSERT_(IsMainThread(), "ProcessEvent can only run in the main thread");
	if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle() && !GetPenDown()) // << HERE
		ReleaseCtrlCapture();
...


And the rest is in the attached Win32Proc.cpp.

Best regards,

Tom

[Updated on: Fri, 26 March 2021 19:25]

Report message to a moderator

Re: Using Pen with U++ [message #56592 is a reply to message #56590] Fri, 26 March 2021 18:19 Go to previous messageGo to previous message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Tom1 wrote on Fri, 26 March 2021 16:44
Mirek,

'case PEN_OTHER:' Looks better than 'case 0:' ... Smile


'default:' is fine too Smile

Quote:


Quote:
Is it so bad to just leave it to LeftDown?


I'm not quite sure what do you mean by this.. (?) (If it is about double clicks, drags or barrel mappings to right mouse button, I can handle them in the application side.)


	bool Pen(Point p, const PenInfo& pn, dword keyflags) override {
		if(keyflags & K_SHIFT)
			return false;
		if(pn.pressure) {
			if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
				drawing.Top().Add(MakeTuple(pn.pressure, p));
			else
				drawing.Add().Add(MakeTuple(pn.pressure, p));
		}
		pen = pn;
		Refresh();
		return true;
	}
	
	void LeftDown(Point p, dword keyflags) override {
		if(keyflags & K_SHIFT) {
			RectTracker tracker(*this);
			tracker.MinSize(Size(-100000,-100000));
			tracker.Track(Rect(p,p));
		}
	}


I mean, the main reason for separated Pen method interface is that we do not want to add support to any client code. So to start adding just that right away is perhaps not the best idea?

Mirek

[Updated on: Fri, 26 March 2021 18:21]

Report message to a moderator

Previous Topic: WString vs Grapheme Cluster idea (with possible flaw)
Next Topic: .gitignore
Goto Forum:
  


Current Time: Wed Apr 24 13:17:48 CEST 2024

Total time taken to generate the page: 0.03667 seconds