From b4231f8df0ae529cce1a36d08fe8315bbf9f35b2 Mon Sep 17 00:00:00 2001 From: Walt Destler Date: Tue, 22 Jun 2010 16:37:17 +0000 Subject: [PATCH] Added ability to receive windowing events in python. Added Windows 7 multitouch support. Makepanda will detect when compiling with the Win7 SDK and turn on Win7 multitouch features. --- .../src/display/customGraphicsWindowProc.cxx | 44 +++++++ panda/src/display/customGraphicsWindowProc.h | 37 ++++++ panda/src/display/display_composite2.cxx | 3 + panda/src/display/graphicsWindow.cxx | 90 ++++++++++++- panda/src/display/graphicsWindow.h | 18 +++ panda/src/display/graphicsWindowProc.cxx | 26 ++++ panda/src/display/graphicsWindowProc.h | 63 +++++++++ panda/src/display/touchInfo.cxx | 54 ++++++++ panda/src/display/touchInfo.h | 56 ++++++++ panda/src/windisplay/winGraphicsWindow.cxx | 122 +++++++++++++++++- panda/src/windisplay/winGraphicsWindow.h | 20 +++ 11 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 panda/src/display/customGraphicsWindowProc.cxx create mode 100644 panda/src/display/customGraphicsWindowProc.h create mode 100644 panda/src/display/graphicsWindowProc.cxx create mode 100644 panda/src/display/graphicsWindowProc.h create mode 100644 panda/src/display/touchInfo.cxx create mode 100644 panda/src/display/touchInfo.h diff --git a/panda/src/display/customGraphicsWindowProc.cxx b/panda/src/display/customGraphicsWindowProc.cxx new file mode 100644 index 0000000000..cab48df3d1 --- /dev/null +++ b/panda/src/display/customGraphicsWindowProc.cxx @@ -0,0 +1,44 @@ +// Filename: customGraphicsWindowProc.cxx +// Created by: Walt Destler (May 2010) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "customGraphicsWindowProc.h" + +CustomGraphicsWindowProc::CustomGraphicsWindowProc(PyObject* handler, PyObject* name){ + _handler = handler; + _name = name; + Py_INCREF(_handler); + Py_INCREF(_name); +} + +CustomGraphicsWindowProc::~CustomGraphicsWindowProc(){ + Py_DECREF(_name); + Py_DECREF(_handler); +} + +#if defined(__WIN32__) || defined(_WIN32) +LONG CustomGraphicsWindowProc::wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){ + PyObject* ret = PyObject_CallFunction(_handler, "IIII", hwnd, msg, wparam, lparam); + Py_XDECREF(ret); + + return 0; +} +#endif + +PyObject* CustomGraphicsWindowProc::get_handler(){ + return _handler; +} + +PyObject* CustomGraphicsWindowProc::get_name(){ + return _name; +} diff --git a/panda/src/display/customGraphicsWindowProc.h b/panda/src/display/customGraphicsWindowProc.h new file mode 100644 index 0000000000..71bfa0e255 --- /dev/null +++ b/panda/src/display/customGraphicsWindowProc.h @@ -0,0 +1,37 @@ +// Filename: customGgraphicswindowProc.h +// Created by: Walt Destler (May 2010) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef CUSTOMGRAPHICSWINDOWPROC_H +#define CUSTOMGRAPHICSWINDOWPROC_H + +#include "graphicsWindowProc.h" + +class CustomGraphicsWindowProc: public GraphicsWindowProc{ +public: + CustomGraphicsWindowProc(PyObject* handler, PyObject* name); + virtual ~CustomGraphicsWindowProc(); + +#if defined(__WIN32__) || defined(_WIN32) + virtual LONG wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); +#endif + + PyObject* get_handler(); + PyObject* get_name(); + +private: + PyObject* _handler; + PyObject* _name; +}; + +#endif //CUSTOMGRAPHICSWINDOWPROC_H \ No newline at end of file diff --git a/panda/src/display/display_composite2.cxx b/panda/src/display/display_composite2.cxx index 543baae355..c1bb7ca216 100644 --- a/panda/src/display/display_composite2.cxx +++ b/panda/src/display/display_composite2.cxx @@ -2,12 +2,15 @@ #include "graphicsStateGuardian.cxx" #include "graphicsThreadingModel.cxx" #include "graphicsWindow.cxx" +#include "graphicsWindowProc.cxx" +#include "customGraphicsWindowProc.cxx" #include "graphicsWindowInputDevice.cxx" #include "lru.cxx" #include "nativeWindowHandle.cxx" #include "parasiteBuffer.cxx" #include "standardMunger.cxx" #include "stencilRenderStates.cxx" +#include "touchInfo.cxx" #include "stereoDisplayRegion.cxx" #include "subprocessWindow.cxx" #ifdef IS_OSX diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index 82661d0566..d12150d2d2 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -77,6 +77,12 @@ GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, //////////////////////////////////////////////////////////////////// GraphicsWindow:: ~GraphicsWindow() { + + // Clean up custom event handlers. + CustomWinProcClasses::iterator iter; + for(iter = _custom_window_proc_classes.begin(); iter != _custom_window_proc_classes.end(); ++iter){ + delete *iter; + } } //////////////////////////////////////////////////////////////////// @@ -910,7 +916,6 @@ mouse_mode_relative() { } - //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::mouse_mode_absolute // Access: Protected, Virtual @@ -921,3 +926,86 @@ void GraphicsWindow:: mouse_mode_absolute() { } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::add_custom_event_handler +// Access: Published +// Description: Adds a custom python event handler to be called +// when a window event occurs. +// +//////////////////////////////////////////////////////////////////// +void GraphicsWindow:: +add_custom_event_handler(PyObject* handler, PyObject* name){ + CustomGraphicsWindowProc* cgwp = new CustomGraphicsWindowProc(handler, name); + _custom_window_proc_classes.insert(cgwp); + add_window_proc(cgwp); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::remove_custom_event_handler +// Access: Published +// Description: Removes the specified custom python event handler. +// +//////////////////////////////////////////////////////////////////// +void GraphicsWindow:: +remove_custom_event_handler(PyObject* name){ + //nassertv(wnd_proc != NULL); + //_window_proc_classes.erase( (GraphicsWindowProc*)wnd_proc ); + list toRemove; + CustomWinProcClasses::iterator iter; + for(iter = _custom_window_proc_classes.begin(); iter != _custom_window_proc_classes.end(); ++iter){ + CustomGraphicsWindowProc* cgwp = *iter; + if(PyObject_Compare(cgwp->get_name(), name) == 0) + toRemove.push_back(cgwp); + } + list::iterator iter2; + for(iter2 = toRemove.begin(); iter2 != toRemove.end(); ++iter2){ + CustomGraphicsWindowProc* cgwp = *iter2; + remove_window_proc(cgwp); + _custom_window_proc_classes.erase(cgwp); + delete cgwp; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::supports_window_procs +// Access: Published, Virtual +// Description: Returns whether this window supports adding of Windows proc handlers. +// +//////////////////////////////////////////////////////////////////// +bool GraphicsWindow::supports_window_procs() const{ + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::is_touch_msg +// Access: Published, Virtual +// Description: Returns whether the specified event msg is a touch message. +// +//////////////////////////////////////////////////////////////////// +bool GraphicsWindow:: +is_touch_msg(UINT msg){ + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::get_num_touches +// Access: Published, Virtual +// Description: Returns the current number of touches on this window. +// +//////////////////////////////////////////////////////////////////// +int GraphicsWindow:: +get_num_touches(){ + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::get_touch_info +// Access: Published, Virtual +// Description: Returns the TouchInfo object describing the specified touch. +// +//////////////////////////////////////////////////////////////////// +TouchInfo GraphicsWindow:: +get_touch_info(int index){ + return TouchInfo(); +} diff --git a/panda/src/display/graphicsWindow.h b/panda/src/display/graphicsWindow.h index 7b21c5c180..d1f9331bc9 100644 --- a/panda/src/display/graphicsWindow.h +++ b/panda/src/display/graphicsWindow.h @@ -19,6 +19,8 @@ #include "graphicsOutput.h" #include "graphicsWindowInputDevice.h" +#include "graphicsWindowProc.h" +#include "customGraphicsWindowProc.h" #include "windowProperties.h" #include "mouseData.h" #include "modifierButtons.h" @@ -29,6 +31,7 @@ #include "lightReMutex.h" #include "pvector.h" #include "windowHandle.h" +#include "touchInfo.h" //////////////////////////////////////////////////////////////////// // Class : GraphicsWindow @@ -84,6 +87,13 @@ PUBLISHED: virtual bool move_pointer(int device, int x, int y); virtual void close_ime(); + void add_custom_event_handler(PyObject* handler, PyObject* name); + void remove_custom_event_handler(PyObject* name); + + virtual bool is_touch_msg(UINT msg); + virtual int get_num_touches(); + virtual TouchInfo get_touch_info(int index); + public: // No need to publish these. bool has_button_event(int device) const; @@ -91,6 +101,11 @@ public: bool has_pointer_event(int device) const; PT(PointerEventList) get_pointer_events(int device); + virtual void add_window_proc( const GraphicsWindowProc* wnd_proc_object ){}; + virtual void remove_window_proc( const GraphicsWindowProc* wnd_proc_object ){}; + virtual void clear_window_procs(){}; + virtual bool supports_window_procs() const; + virtual int verify_window_sizes(int numsizes, int *dimen); public: @@ -143,6 +158,9 @@ private: WindowProperties _rejected_properties; string _window_event; string _close_request_event; + + typedef pset CustomWinProcClasses; + CustomWinProcClasses _custom_window_proc_classes; public: static TypeHandle get_class_type() { diff --git a/panda/src/display/graphicsWindowProc.cxx b/panda/src/display/graphicsWindowProc.cxx new file mode 100644 index 0000000000..93bfd79e08 --- /dev/null +++ b/panda/src/display/graphicsWindowProc.cxx @@ -0,0 +1,26 @@ +// Filename: graphicsWindowProc.cxx +// Created by: Bei (Mar2010) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "graphicsWindowProc.h" + +TypeHandle GraphicsWindowProc::_type_handle; + +GraphicsWindowProc::GraphicsWindowProc(){ +} +#if defined(__WIN32__) || defined(_WIN32) +LONG GraphicsWindowProc::wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){ + return 0; +} +#endif +//most an empty file. \ No newline at end of file diff --git a/panda/src/display/graphicsWindowProc.h b/panda/src/display/graphicsWindowProc.h new file mode 100644 index 0000000000..6093526b71 --- /dev/null +++ b/panda/src/display/graphicsWindowProc.h @@ -0,0 +1,63 @@ +// Filename: graphicswindowProc.h +// Created by: Bei Yang (Mar 2010) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +#ifndef GRAPHICSWINDOWPROC_H +#define GRAPHICSWINDOWPROC_H + +#include "pandabase.h" +#include "typedReferenceCount.h" + +#if defined(__WIN32__) || defined(_WIN32) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 + #endif + #include +#endif + +/* +Defines a little interface for storing a platform specific window +processor methods. Since this is a purely virtual class, it never +really gets instaniated so this even though this is type reference +counted, it doesn't need to registered. +*/ +class EXPCL_PANDA_DISPLAY GraphicsWindowProc: public TypedReferenceCount{ +public: + GraphicsWindowProc(); +#if defined(__WIN32__) || defined(_WIN32) + virtual LONG wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); +#endif + //purely virtual class + + // In theory, this stuff below never gets used since it's purely virtual + // class that can't be instaniated anyways +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "GraphicsWindowProc", + TypedReferenceCount::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#endif //GRAPHICSWINDOWPROC_H \ No newline at end of file diff --git a/panda/src/display/touchInfo.cxx b/panda/src/display/touchInfo.cxx new file mode 100644 index 0000000000..eeccc3af26 --- /dev/null +++ b/panda/src/display/touchInfo.cxx @@ -0,0 +1,54 @@ +// Filename: touchInfo.cxx +// Created by: Walt Destler (May 25, 2010) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "touchInfo.h" + +TouchInfo::TouchInfo(){ + _x = 0; + _y = 0; + _id = 0; + _flags = 0; +} + +LONG TouchInfo::get_x(){ + return _x; +} + +LONG TouchInfo::get_y(){ + return _y; +} + +DWORD TouchInfo::get_id(){ + return _id; +} + +DWORD TouchInfo::get_flags(){ + return _flags; +} + +void TouchInfo::set_x(LONG x){ + _x = x; +} + +void TouchInfo::set_y(LONG y){ + _y = y; +} + +void TouchInfo::set_id(DWORD id){ + _id = id; +} + +void TouchInfo::set_flags(DWORD flags){ + _flags = flags; +} diff --git a/panda/src/display/touchInfo.h b/panda/src/display/touchInfo.h new file mode 100644 index 0000000000..1087026813 --- /dev/null +++ b/panda/src/display/touchInfo.h @@ -0,0 +1,56 @@ +// Filename: touchInfo.h +// Created by: Walt Destler (May 25, 2010) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef TOUCHINFO_H +#define TOUCHINFO_H + +//////////////////////////////////////////////////////////////////// +// Class : TouchInfo +// Description : Stores information for a single touch event. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_DISPLAY TouchInfo { + +PUBLISHED: + enum TouchInfoFlags + { + TIF_move = 0x0001, + TIF_down = 0x0002, + TIF_UP = 0x0004, + }; + +public: + + TouchInfo(); + + void set_x(LONG x); + void set_y(LONG y); + void set_id(DWORD id); + void set_flags(DWORD flags); + +PUBLISHED: + + LONG get_x(); + LONG get_y(); + DWORD get_id(); + DWORD get_flags(); + +private: + + LONG _x; + LONG _y; + DWORD _id; + DWORD _flags; +}; + +#endif diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 7f65baa46d..e39a2baf4a 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -31,7 +31,6 @@ - TypeHandle WinGraphicsWindow::_type_handle; TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle; @@ -109,6 +108,9 @@ WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, _lalt_down = false; _ralt_down = false; _hparent = NULL; +#ifdef PANDA_WIN7 + _numTouches = 0; +#endif } //////////////////////////////////////////////////////////////////// @@ -470,6 +472,11 @@ open_window() { // set us as the focus window for keyboard input set_focus(); + + // Register for Win7 touch events. +#ifdef PANDA_WIN7 + RegisterTouchWindow(_hWnd, 0); +#endif return true; } @@ -2071,6 +2078,21 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { properties.set_foreground(false); system_changed_properties(properties); break; + +#ifdef PANDA_WIN7 + case WM_TOUCH: + _numTouches = LOWORD(wparam); + if(_numTouches > MAX_TOUCHES) + _numTouches = MAX_TOUCHES; + GetTouchInputInfo((HTOUCHINPUT)lparam, _numTouches, _touches, sizeof(TOUCHINPUT)); + CloseTouchInputHandle((HTOUCHINPUT)lparam); + break; +#endif + } + + //do custom messages processing if any has been set + for ( WinProcClasses::iterator it=_window_proc_classes.begin() ; it != _window_proc_classes.end(); it++ ){ + (*it)->wnd_proc(hwnd, msg, wparam, lparam); } return DefWindowProc(hwnd, msg, wparam, lparam); @@ -2793,3 +2815,101 @@ void get_client_rect_screen(HWND hwnd, RECT *view_rect) { view_rect->right = lr.x; view_rect->bottom = lr.y; } + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::add_window_proc +// Access: Public, Virtual +// Description: Adds the specified Windows proc event handler to be called +// whenever a Windows event occurs. +// +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow::add_window_proc( const GraphicsWindowProc* wnd_proc ){ + nassertv(wnd_proc != NULL); + _window_proc_classes.insert( (GraphicsWindowProc*)wnd_proc ); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::remove_window_proc +// Access: Public, Virtual +// Description: Removes the specified Windows proc event handler. +// +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow::remove_window_proc( const GraphicsWindowProc* wnd_proc ){ + nassertv(wnd_proc != NULL); + _window_proc_classes.erase( (GraphicsWindowProc*)wnd_proc ); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::clear_window_procs +// Access: Public, Virtual +// Description: Removes all Windows proc event handlers. +// +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow::clear_window_procs(){ + _window_proc_classes.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::supports_window_procs +// Access: Public, Virtual +// Description: Returns whether this window supports adding of windows proc handlers. +// +//////////////////////////////////////////////////////////////////// +bool WinGraphicsWindow::supports_window_procs() const{ + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::is_touch_msg +// Access: Public, Virtual +// Description: Returns whether the specified event msg is a touch message. +// +//////////////////////////////////////////////////////////////////// +bool WinGraphicsWindow::is_touch_msg(UINT msg){ +#ifdef PANDA_WIN7 + return msg == WM_TOUCH; +#else + return false; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::get_num_touches +// Access: Public, Virtual +// Description: Returns the current number of touches on this window. +// +//////////////////////////////////////////////////////////////////// +int WinGraphicsWindow:: +get_num_touches(){ +#ifdef PANDA_WIN7 + return _numTouches; +#else + return 0; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::get_touch_info +// Access: Public, Virtual +// Description: Returns the TouchInfo object describing the specified touch. +// +//////////////////////////////////////////////////////////////////// +TouchInfo WinGraphicsWindow:: +get_touch_info(int index){ +#ifdef PANDA_WIN7 + TOUCHINPUT ti = _touches[index]; + POINT point; + point.x = TOUCH_COORD_TO_PIXEL(ti.x); + point.y = TOUCH_COORD_TO_PIXEL(ti.y); + ScreenToClient(_hWnd, &point); + + TouchInfo ret = TouchInfo(); + ret.set_x(point.x); + ret.set_y(point.y); + ret.set_id(ti.dwID); + ret.set_flags(ti.dwFlags); + return ret; +#else + return TouchInfo(); +#endif +} diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 1428826fa4..9732903e01 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -28,6 +28,8 @@ class WinGraphicsPipe; #define PM_INACTIVE (WM_APP+124) +#define MAX_TOUCHES 20 + typedef struct { int x; int y; @@ -76,6 +78,14 @@ public: INLINE HWND get_ime_hwnd(); + virtual void add_window_proc( const GraphicsWindowProc* wnd_proc_object ); + virtual void remove_window_proc( const GraphicsWindowProc* wnd_proc_object ); + virtual void clear_window_procs(); + virtual bool supports_window_procs() const; + + virtual bool is_touch_msg(UINT msg); + virtual int get_num_touches(); + virtual TouchInfo get_touch_info(int index); protected: virtual void close_window(); @@ -178,6 +188,16 @@ private: bool _lalt_down; bool _ralt_down; + // following adds support platform specfic window processing + // functions. + typedef pset WinProcClasses; + WinProcClasses _window_proc_classes; + +#ifdef PANDA_WIN7 + UINT _numTouches; + TOUCHINPUT _touches[MAX_TOUCHES]; +#endif + private: // We need this map to support per-window calls to window_proc(). typedef map WindowHandles;