/** * 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." * * @file winGraphicsWindow.h * @author drose * @date 2002-12-20 */ #ifndef WINGRAPHICSWINDOW_H #define WINGRAPHICSWINDOW_H #include "pandabase.h" #include "graphicsWindow.h" #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include class WinGraphicsPipe; #define PM_ACTIVE (WM_APP+123) #define PM_INACTIVE (WM_APP+124) #define MAX_TOUCHES 20 typedef struct { int x; int y; int width; int height; } WINDOW_METRICS; #if WINVER < 0x0601 // Not used on Windows XP, but we still need to define it. typedef struct tagTOUCHINPUT { LONG x; LONG y; HANDLE hSource; DWORD dwID; DWORD dwFlags; DWORD dwMask; DWORD dwTime; ULONG_PTR dwExtraInfo; DWORD cxContact; DWORD cyContact; } TOUCHINPUT, *PTOUCHINPUT; #endif /** * An abstract base class for glGraphicsWindow and dxGraphicsWindow (and, in * general, graphics windows that interface with the Microsoft Windows API). * * This class includes all the code for manipulating windows themselves: * opening them, closing them, responding to user keyboard and mouse input, * and so on. It does not make any 3-D rendering calls into the window; that * is the province of the GraphicsStateGuardian. */ class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow { public: WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, const std::string &name, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg, GraphicsOutput *host); virtual ~WinGraphicsWindow(); virtual MouseData get_pointer(int device) const; virtual bool move_pointer(int device, int x, int y); virtual void close_ime(); virtual void begin_flip(); virtual void process_events(); virtual void set_properties_now(WindowProperties &properties); void receive_windows_message(unsigned int msg, int wparam, int lparam); virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); virtual bool handle_mouse_motion(int x, int y); virtual void handle_mouse_exit(); 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_event(GraphicsWindowProcCallbackData* callbackData); virtual int get_num_touches(); virtual TouchInfo get_touch_info(int index); protected: void trigger_flip(); virtual void close_window(); virtual bool open_window(); virtual void fullscreen_minimized(WindowProperties &properties); virtual void fullscreen_restored(WindowProperties &properties); virtual bool do_reshape_request(int x_origin, int y_origin, bool has_origin, int x_size, int y_size); virtual void handle_reshape(); virtual bool do_fullscreen_resize(int x_size, int y_size); virtual bool do_fullscreen_switch(); virtual bool do_windowed_switch(); virtual bool do_fullscreen_enable(); virtual bool do_fullscreen_disable(); virtual bool calculate_metrics(bool fullscreen, DWORD style, WINDOW_METRICS &metrics, bool &has_origin); DWORD make_style(const WindowProperties &properties); virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, DWORD &bitdepth); virtual void support_overlay_window(bool flag); private: bool open_graphic_window(); void adjust_z_order(); void adjust_z_order(WindowProperties::ZOrder last_z_order, WindowProperties::ZOrder this_z_order); void initialize_input_devices(); void handle_raw_input(HRAWINPUT hraw); void track_mouse_leaving(HWND hwnd); void set_focus(); static void process_1_event(); void handle_keypress(ButtonHandle key, int x, int y, double time); void handle_keyresume(ButtonHandle key, double time); void handle_keyrelease(ButtonHandle key, double time); void handle_raw_keypress(ButtonHandle key, double time); void handle_raw_keyrelease(ButtonHandle key, double time); ButtonHandle lookup_key(WPARAM wparam) const; ButtonHandle lookup_raw_key(LPARAM lparam) const; virtual ButtonMap *get_keyboard_map() const; INLINE int translate_mouse(int pos) const; INLINE void set_cursor_in_window(); INLINE void set_cursor_out_of_window(); INLINE static double get_message_time(); void resend_lost_keypresses(); void release_all_buttons(); static void update_cursor_window(WinGraphicsWindow *to_window); static void hide_or_show_cursor(bool hide_cursor); static bool find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp, DEVMODE &dm); static void show_error_message(DWORD message_id = 0); protected: HWND _hWnd; HWND _hparent; private: HWND _ime_hWnd; bool _ime_open; bool _ime_active; bool _tracking_mouse_leaving; bool _bCursor_in_WindowClientArea; HANDLE _input_device_handle[32]; HCURSOR _cursor; DEVMODE _fullscreen_display_mode; bool _lost_keypresses; // These are used to store the status of the individual left and right // shift, control, and alt keys. Keyboard events are not sent for these // individual keys, but for each pair as a whole. The status of each key // must be checked as keypress and keyrelease events are received. bool _lshift_down; bool _rshift_down; bool _lcontrol_down; bool _rcontrol_down; bool _lalt_down; bool _ralt_down; GraphicsWindowInputDevice *_input; // following adds support platform specfic window processing functions. typedef pset WinProcClasses; WinProcClasses _window_proc_classes; UINT _num_touches; TOUCHINPUT _touches[MAX_TOUCHES]; private: // We need this map to support per-window calls to window_proc(). typedef std::map WindowHandles; static WindowHandles _window_handles; // And we need a static pointer to the current WinGraphicsWindow we are // creating at the moment, since CreateWindow() starts generating window // events before it gives us the window handle. static WinGraphicsWindow *_creating_window; /* * This tracks the current GraphicsWindow whose client area contains the * mouse. There will only be one of these at a time, and storing the pointer * here allows us to handle ambiguities in the order in which messages are * passed from Windows to the various windows we manage. This pointer is used * by set_cursor_in_window() to determine when it is time to call * update_cursor() to hide the cursor (or do other related operations). */ static WinGraphicsWindow *_cursor_window; static bool _cursor_hidden; static bool _got_saved_params; static int _saved_mouse_trails; static BOOL _saved_cursor_shadow; static BOOL _saved_mouse_vanish; // The mouse constraints before applying mouse mode M_confined. static RECT _mouse_unconfined_cliprect; // Since the Panda API requests icons and cursors by filename, we need a // table mapping filenames to handles, so we can avoid re-reading the file // each time we change icons. typedef pmap IconFilenames; static IconFilenames _icon_filenames; static IconFilenames _cursor_filenames; static HICON get_icon(const Filename &filename); static HCURSOR get_cursor(const Filename &filename); // The table of window classes we have registered. We need to register a // different window class for each different window icon (the cursor we can // specify dynamically, later). We might have other requirements too, // later. class WindowClass { public: INLINE WindowClass(const WindowProperties &props); INLINE bool operator < (const WindowClass &other) const; std::wstring _name; HICON _icon; }; typedef pset WindowClasses; static WindowClasses _window_classes; static int _window_class_index; static const WindowClass ®ister_window_class(const WindowProperties &props); private: // This subclass of WindowHandle is stored in _window_handle to represent // this particular window. We use it to add hooks for communicating with // the parent window, in particular to receive keyboard events from the // parent window when necessary. class WinWindowHandle : public WindowHandle { public: WinWindowHandle(WinGraphicsWindow *window, const WindowHandle ©); void clear_window(); protected: virtual void receive_windows_message(unsigned int msg, int wparam, int lparam); private: // Not reference-counted, to avoid a circular reference count. WinGraphicsWindow *_window; public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { WindowHandle::init_type(); register_type(_type_handle, "WinWindowHandle", WindowHandle::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; }; public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { GraphicsWindow::init_type(); register_type(_type_handle, "WinGraphicsWindow", GraphicsWindow::get_class_type()); WinWindowHandle::init_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; }; #define PRINT_LAST_ERROR 0 extern EXPCL_PANDAWIN void PrintErrorMessage(DWORD msgID); extern EXPCL_PANDAWIN void ClearToBlack(HWND hWnd, const WindowProperties &props); extern EXPCL_PANDAWIN void get_client_rect_screen(HWND hwnd, RECT *view_rect); #include "winGraphicsWindow.I" #endif