diff options
Diffstat (limited to 'intern/ghost')
-rw-r--r-- | intern/ghost/CMakeLists.txt | 6 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWayland.cpp | 285 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWayland.h | 17 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 73 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WaylandCursorSettings.h | 130 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWayland.cpp | 130 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWayland.h | 17 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 45 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.h | 168 |
9 files changed, 512 insertions, 359 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index f90e8a973bf..1b5cdb3cda0 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -282,6 +282,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) ${wayland-egl_INCLUDE_DIRS} ${xkbcommon_INCLUDE_DIRS} ${wayland-cursor_INCLUDE_DIRS} + ${dbus_INCLUDE_DIRS} ) list(APPEND SRC @@ -321,6 +322,11 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) xdg-shell "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml" ) + # xdg-decoration. + generate_protocol_bindings( + xdg-decoration + "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" + ) # Pointer-constraints. generate_protocol_bindings( pointer-constraints diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 81d9824ed26..83b9b2ba36b 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -40,6 +40,7 @@ #include <unordered_map> #include <unordered_set> +#include "GHOST_WaylandCursorSettings.h" #include <pointer-constraints-client-protocol.h> #include <relative-pointer-client-protocol.h> #include <wayland-cursor.h> @@ -52,15 +53,6 @@ #include <cstring> -struct output_t { - struct wl_output *output; - int32_t width, height; - int transform; - int scale; - std::string make; - std::string model; -}; - struct buffer_t { void *data; size_t size; @@ -72,6 +64,12 @@ struct cursor_t { struct wl_buffer *buffer; struct wl_cursor_image image; struct buffer_t *file_buffer = nullptr; + struct wl_cursor_theme *theme = nullptr; + int size; + std::string theme_name; + // outputs on which the cursor is visible + std::unordered_set<const output_t *> outputs; + int scale = 1; }; struct data_offer_t { @@ -142,10 +140,14 @@ struct display_t { struct wl_display *display; struct wl_compositor *compositor = nullptr; struct xdg_wm_base *xdg_shell = nullptr; + struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr; struct wl_shm *shm = nullptr; std::vector<output_t *> outputs; std::vector<input_t *> inputs; - struct wl_cursor_theme *cursor_theme = nullptr; + struct { + std::string theme; + int size; + } cursor; struct wl_data_device_manager *data_device_manager = nullptr; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; @@ -154,6 +156,8 @@ struct display_t { std::vector<struct wl_egl_window *> os_egl_windows; }; +static GHOST_WindowManager *window_manager = nullptr; + static void display_destroy(display_t *d) { if (d->data_device_manager) { @@ -188,6 +192,9 @@ static void display_destroy(display_t *d) if (input->cursor.surface) { wl_surface_destroy(input->cursor.surface); } + if (input->cursor.theme) { + wl_cursor_theme_destroy(input->cursor.theme); + } if (input->pointer) { wl_pointer_destroy(input->pointer); } @@ -210,10 +217,6 @@ static void display_destroy(display_t *d) delete input; } - if (d->cursor_theme) { - wl_cursor_theme_destroy(d->cursor_theme); - } - if (d->shm) { wl_shm_destroy(d->shm); } @@ -238,6 +241,10 @@ static void display_destroy(display_t *d) wl_compositor_destroy(d->compositor); } + if (d->xdg_decoration_manager) { + zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager); + } + if (d->xdg_shell) { xdg_wm_base_destroy(d->xdg_shell); } @@ -478,7 +485,9 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event) static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive) { int pipefd[2]; - pipe(pipefd); + if (pipe(pipefd) != 0) { + return {}; + } wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); close(pipefd[1]); @@ -513,7 +522,9 @@ static void data_source_send(void *data, int32_t fd) { const char *const buffer = static_cast<char *>(data); - write(fd, buffer, strlen(buffer) + 1); + if (write(fd, buffer, strlen(buffer) + 1) < 0) { + GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl); + } close(fd); } @@ -789,13 +800,80 @@ static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer) cursor_t *cursor = static_cast<cursor_t *>(data); wl_buffer_destroy(wl_buffer); - cursor->buffer = nullptr; + + if (wl_buffer == cursor->buffer) { + /* the mapped buffer was from a custom cursor */ + cursor->buffer = nullptr; + } } const struct wl_buffer_listener cursor_buffer_listener = { cursor_buffer_release, }; +static GHOST_IWindow *get_window(struct wl_surface *surface) +{ + if (!surface) { + return nullptr; + } + + for (GHOST_IWindow *win : window_manager->getWindows()) { + if (surface == static_cast<const GHOST_WindowWayland *>(win)->surface()) { + return win; + } + } + return nullptr; +} + +static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm) +{ + int scale = 0; + for (const output_t *output : cursor.outputs) { + if (output->scale > scale) + scale = output->scale; + } + + if (scale > 0 && cursor.scale != scale) { + cursor.scale = scale; + wl_surface_set_buffer_scale(cursor.surface, scale); + wl_cursor_theme_destroy(cursor.theme); + cursor.theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm); + return true; + } + return false; +} + +static void cursor_surface_enter(void *data, + struct wl_surface * /*wl_surface*/, + struct wl_output *output) +{ + input_t *input = static_cast<input_t *>(data); + for (const output_t *reg_output : input->system->outputs()) { + if (reg_output->output == output) { + input->cursor.outputs.insert(reg_output); + } + } + update_cursor_scale(input->cursor, input->system->shm()); +} + +static void cursor_surface_leave(void *data, + struct wl_surface * /*wl_surface*/, + struct wl_output *output) +{ + input_t *input = static_cast<input_t *>(data); + for (const output_t *reg_output : input->system->outputs()) { + if (reg_output->output == output) { + input->cursor.outputs.erase(reg_output); + } + } + update_cursor_scale(input->cursor, input->system->shm()); +} + +struct wl_surface_listener cursor_surface_listener = { + cursor_surface_enter, + cursor_surface_leave, +}; + static void pointer_enter(void *data, struct wl_pointer * /*wl_pointer*/, uint32_t serial, @@ -803,22 +881,28 @@ static void pointer_enter(void *data, wl_fixed_t surface_x, wl_fixed_t surface_y) { - if (!surface) { + GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(surface)); + + if (!win) { return; } + + win->activate(); + input_t *input = static_cast<input_t *>(data); input->pointer_serial = serial; - input->x = wl_fixed_to_int(surface_x); - input->y = wl_fixed_to_int(surface_y); + input->x = win->scale() * wl_fixed_to_int(surface_x); + input->y = win->scale() * wl_fixed_to_int(surface_y); input->focus_pointer = surface; - input->system->pushEvent( - new GHOST_EventCursor(input->system->getMilliSeconds(), - GHOST_kEventCursorMove, - static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface)), - input->x, - input->y, - GHOST_TABLET_DATA_NONE)); + win->setCursorShape(win->getCursorShape()); + + input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + static_cast<GHOST_WindowWayland *>(win), + input->x, + input->y, + GHOST_TABLET_DATA_NONE)); } static void pointer_leave(void *data, @@ -826,9 +910,14 @@ static void pointer_leave(void *data, uint32_t /*serial*/, struct wl_surface *surface) { - if (surface != nullptr) { - static_cast<input_t *>(data)->focus_pointer = nullptr; + GHOST_IWindow *win = get_window(surface); + + if (!win) { + return; } + + static_cast<input_t *>(data)->focus_pointer = nullptr; + static_cast<GHOST_WindowWayland *>(win)->deactivate(); } static void pointer_motion(void *data, @@ -839,21 +928,20 @@ static void pointer_motion(void *data, { input_t *input = static_cast<input_t *>(data); - GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>( - wl_surface_get_user_data(input->focus_pointer)); + GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(input->focus_pointer)); if (!win) { return; } - input->x = wl_fixed_to_int(surface_x); - input->y = wl_fixed_to_int(surface_y); + input->x = win->scale() * wl_fixed_to_int(surface_x); + input->y = win->scale() * wl_fixed_to_int(surface_y); input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, win, - wl_fixed_to_int(surface_x), - wl_fixed_to_int(surface_y), + input->x, + input->y, GHOST_TABLET_DATA_NONE)); } @@ -864,6 +952,14 @@ static void pointer_button(void *data, uint32_t button, uint32_t state) { + input_t *input = static_cast<input_t *>(data); + + GHOST_IWindow *win = get_window(input->focus_pointer); + + if (!win) { + return; + } + GHOST_TEventType etype = GHOST_kEventUnknown; switch (state) { case WL_POINTER_BUTTON_STATE_RELEASED: @@ -887,9 +983,6 @@ static void pointer_button(void *data, break; } - input_t *input = static_cast<input_t *>(data); - GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>( - wl_surface_get_user_data(input->focus_pointer)); input->data_source->source_serial = serial; input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); input->system->pushEvent(new GHOST_EventButton( @@ -902,12 +995,18 @@ static void pointer_axis(void *data, uint32_t axis, wl_fixed_t value) { + input_t *input = static_cast<input_t *>(data); + + GHOST_IWindow *win = get_window(input->focus_pointer); + + if (!win) { + return; + } + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { return; } - input_t *input = static_cast<input_t *>(data); - GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>( - wl_surface_get_user_data(input->focus_pointer)); + input->system->pushEvent( new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1)); } @@ -1137,7 +1236,12 @@ static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capa input->cursor.visible = true; input->cursor.buffer = nullptr; input->cursor.file_buffer = new buffer_t; + if (!get_cursor_settings(input->cursor.theme_name, input->cursor.size)) { + input->cursor.theme_name = std::string(); + input->cursor.size = default_cursor_size; + } wl_pointer_add_listener(input->pointer, &pointer_listener, data); + wl_surface_add_listener(input->cursor.surface, &cursor_surface_listener, data); } if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { @@ -1160,8 +1264,8 @@ static void output_geometry(void *data, struct wl_output * /*wl_output*/, int32_t /*x*/, int32_t /*y*/, - int32_t /*physical_width*/, - int32_t /*physical_height*/, + int32_t physical_width, + int32_t physical_height, int32_t /*subpixel*/, const char *make, const char *model, @@ -1171,6 +1275,8 @@ static void output_geometry(void *data, output->transform = transform; output->make = std::string(make); output->model = std::string(model); + output->width_mm = physical_width; + output->height_mm = physical_height; } static void output_mode(void *data, @@ -1181,8 +1287,8 @@ static void output_mode(void *data, int32_t /*refresh*/) { output_t *output = static_cast<output_t *>(data); - output->width = width; - output->height = height; + output->width_pxl = width; + output->height_pxl = height; } /** @@ -1227,13 +1333,17 @@ static void global_add(void *data, struct display_t *display = static_cast<struct display_t *>(data); if (!strcmp(interface, wl_compositor_interface.name)) { display->compositor = static_cast<wl_compositor *>( - wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1)); + wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3)); } else if (!strcmp(interface, xdg_wm_base_interface.name)) { display->xdg_shell = static_cast<xdg_wm_base *>( wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1)); xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr); } + else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)) { + display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>( + wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1)); + } else if (!strcmp(interface, wl_output_interface.name)) { output_t *output = new output_t; output->scale = 1; @@ -1335,16 +1445,6 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t) wl_data_device_add_listener(input->data_device, &data_device_listener, input); } } - - const char *theme = std::getenv("XCURSOR_THEME"); - const char *size = std::getenv("XCURSOR_SIZE"); - const int sizei = size ? std::stoi(size) : default_cursor_size; - - d->cursor_theme = wl_cursor_theme_load(theme, sizei, d->shm); - if (!d->cursor_theme) { - display_destroy(d); - throw std::runtime_error("Wayland: unable to access cursor themes!"); - } } GHOST_SystemWayland::~GHOST_SystemWayland() @@ -1471,8 +1571,8 @@ void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TU { if (getNumDisplays() > 0) { /* We assume first output as main. */ - width = uint32_t(d->outputs[0]->width); - height = uint32_t(d->outputs[0]->height); + width = uint32_t(d->outputs[0]->width_pxl) / d->outputs[0]->scale; + height = uint32_t(d->outputs[0]->height_pxl) / d->outputs[0]->scale; } } @@ -1481,7 +1581,7 @@ void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUn getMainDisplayDimensions(width, height); } -GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glSettings) +GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/) { /* Create new off-screen window. */ wl_surface *os_surface = wl_compositor_create_surface(compositor()); @@ -1530,6 +1630,11 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, const bool is_dialog, const GHOST_IWindow *parentWindow) { + /* globally store pointer to window manager */ + if (!window_manager) { + window_manager = getWindowManager(); + } + GHOST_WindowWayland *window = new GHOST_WindowWayland( this, title, @@ -1574,6 +1679,21 @@ xdg_wm_base *GHOST_SystemWayland::shell() return d->xdg_shell; } +zxdg_decoration_manager_v1 *GHOST_SystemWayland::decoration_manager() +{ + return d->xdg_decoration_manager; +} + +const std::vector<output_t *> &GHOST_SystemWayland::outputs() const +{ + return d->outputs; +} + +wl_shm *GHOST_SystemWayland::shm() const +{ + return d->shm; +} + void GHOST_SystemWayland::setSelection(const std::string &selection) { this->selection = selection; @@ -1581,23 +1701,20 @@ void GHOST_SystemWayland::setSelection(const std::string &selection) static void set_cursor_buffer(input_t *input, wl_buffer *buffer) { - input->cursor.visible = (buffer != nullptr); + cursor_t *c = &input->cursor; - wl_surface_attach(input->cursor.surface, buffer, 0, 0); - wl_surface_commit(input->cursor.surface); + c->visible = (buffer != nullptr); - if (input->cursor.visible) { - wl_surface_damage(input->cursor.surface, - 0, - 0, - int32_t(input->cursor.image.width), - int32_t(input->cursor.image.height)); - wl_pointer_set_cursor(input->pointer, - input->pointer_serial, - input->cursor.surface, - int32_t(input->cursor.image.hotspot_x), - int32_t(input->cursor.image.hotspot_y)); - } + wl_surface_attach(c->surface, buffer, 0, 0); + + wl_surface_damage(c->surface, 0, 0, int32_t(c->image.width), int32_t(c->image.height)); + wl_pointer_set_cursor(input->pointer, + input->pointer_serial, + c->visible ? c->surface : nullptr, + int32_t(c->image.hotspot_x) / c->scale, + int32_t(c->image.hotspot_y) / c->scale); + + wl_surface_commit(c->surface); } GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) @@ -1608,7 +1725,15 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) : cursors.at(GHOST_kStandardCursorDefault); - wl_cursor *cursor = wl_cursor_theme_get_cursor(d->cursor_theme, cursor_name.c_str()); + input_t *input = d->inputs[0]; + cursor_t *c = &input->cursor; + + if (!c->theme) { + /* The cursor surface hasn't entered an output yet. Initialize theme with scale 1. */ + c->theme = wl_cursor_theme_load(c->theme_name.c_str(), c->size, d->inputs[0]->system->shm()); + } + + wl_cursor *cursor = wl_cursor_theme_get_cursor(c->theme, cursor_name.c_str()); if (!cursor) { GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); @@ -1620,11 +1745,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) if (!buffer) { return GHOST_kFailure; } - cursor_t *c = &d->inputs[0]->cursor; + c->buffer = buffer; c->image = *image; - set_cursor_buffer(d->inputs[0], buffer); + set_cursor_buffer(input, buffer); return GHOST_kSuccess; } @@ -1735,6 +1860,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode, wl_surface *surface) { + /* ignore, if the required protocols are not supported */ + if (!d->relative_pointer_manager || !d->pointer_constraints) { + return GHOST_kFailure; + } + if (d->inputs.empty()) { return GHOST_kFailure; } @@ -1754,6 +1884,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo break; case GHOST_kGrabNormal: + break; case GHOST_kGrabWrap: input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( d->relative_pointer_manager, input->pointer); diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 10b9ef6bd62..3a08a0d3b16 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -26,6 +26,7 @@ #include "GHOST_WindowWayland.h" #include <wayland-client.h> +#include <xdg-decoration-client-protocol.h> #include <xdg-shell-client-protocol.h> #include <string> @@ -34,6 +35,16 @@ class GHOST_WindowWayland; struct display_t; +struct output_t { + struct wl_output *output; + int32_t width_pxl, height_pxl; // dimensions in pixel + int32_t width_mm, height_mm; // dimensions in millimeter + int transform; + int scale; + std::string make; + std::string model; +}; + class GHOST_SystemWayland : public GHOST_System { public: GHOST_SystemWayland(); @@ -84,6 +95,12 @@ class GHOST_SystemWayland : public GHOST_System { xdg_wm_base *shell(); + zxdg_decoration_manager_v1 *decoration_manager(); + + const std::vector<output_t *> &outputs() const; + + wl_shm *shm() const; + void setSelection(const std::string &selection); GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape); diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 38dea9c1142..fc3cb81e26a 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -32,6 +32,7 @@ #include <commctrl.h> #include <psapi.h> #include <shellapi.h> +#include <shellscalingapi.h> #include <shlobj.h> #include <tlhelp32.h> #include <windowsx.h> @@ -97,41 +98,6 @@ # define VK_GR_LESS 0xE2 #endif // VK_GR_LESS -#ifndef VK_MEDIA_NEXT_TRACK -# define VK_MEDIA_NEXT_TRACK 0xB0 -#endif // VK_MEDIA_NEXT_TRACK -#ifndef VK_MEDIA_PREV_TRACK -# define VK_MEDIA_PREV_TRACK 0xB1 -#endif // VK_MEDIA_PREV_TRACK -#ifndef VK_MEDIA_STOP -# define VK_MEDIA_STOP 0xB2 -#endif // VK_MEDIA_STOP -#ifndef VK_MEDIA_PLAY_PAUSE -# define VK_MEDIA_PLAY_PAUSE 0xB3 -#endif // VK_MEDIA_PLAY_PAUSE - -// Window message newer than Windows 7 -#ifndef WM_DPICHANGED -# define WM_DPICHANGED 0x02E0 -#endif // WM_DPICHANGED - -// WM_POINTER API messages minimum Windows 7 -#ifndef WM_POINTERENTER -# define WM_POINTERENTER 0x0249 -#endif // WM_POINTERENTER -#ifndef WM_POINTERDOWN -# define WM_POINTERDOWN 0x0246 -#endif // WM_POINTERDOWN -#ifndef WM_POINTERUPDATE -# define WM_POINTERUPDATE 0x0245 -#endif // WM_POINTERUPDATE -#ifndef WM_POINTERUP -# define WM_POINTERUP 0x0247 -#endif // WM_POINTERUP -#ifndef WM_POINTERLEAVE -# define WM_POINTERLEAVE 0x024A -#endif // WM_POINTERLEAVE - /* Workaround for some laptop touchpads, some of which seems to * have driver issues which makes it so window function receives * the message, but PeekMessage doesn't pick those messages for @@ -173,24 +139,6 @@ static void initRawInput() #undef DEVICE_COUNT } -#ifndef DPI_ENUMS_DECLARED -typedef enum PROCESS_DPI_AWARENESS { - PROCESS_DPI_UNAWARE = 0, - PROCESS_SYSTEM_DPI_AWARE = 1, - PROCESS_PER_MONITOR_DPI_AWARE = 2 -} PROCESS_DPI_AWARENESS; - -typedef enum MONITOR_DPI_TYPE { - MDT_EFFECTIVE_DPI = 0, - MDT_ANGULAR_DPI = 1, - MDT_RAW_DPI = 2, - MDT_DEFAULT = MDT_EFFECTIVE_DPI -} MONITOR_DPI_TYPE; - -# define USER_DEFAULT_SCREEN_DPI 96 - -# define DPI_ENUMS_DECLARED -#endif typedef HRESULT(API *GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); typedef BOOL(API *GHOST_WIN32_EnableNonClientDpiScaling)(HWND); @@ -205,15 +153,7 @@ GHOST_SystemWin32::GHOST_SystemWin32() // Tell Windows we are per monitor DPI aware. This disables the default // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI. - HMODULE m_shcore = ::LoadLibrary("Shcore.dll"); - if (m_shcore) { - GHOST_WIN32_SetProcessDpiAwareness fpSetProcessDpiAwareness = - (GHOST_WIN32_SetProcessDpiAwareness)::GetProcAddress(m_shcore, "SetProcessDpiAwareness"); - - if (fpSetProcessDpiAwareness) { - fpSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); - } - } + SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); // Check if current keyboard layout uses AltGr and save keylayout ID for // specialized handling if keys like VK_OEM_*. I.e. french keylayout @@ -581,14 +521,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() InitCommonControls(); /* Disable scaling on high DPI displays on Vista */ - HMODULE - user32 = ::LoadLibraryA("user32.dll"); - typedef BOOL(WINAPI * LPFNSETPROCESSDPIAWARE)(); - LPFNSETPROCESSDPIAWARE SetProcessDPIAware = (LPFNSETPROCESSDPIAWARE)GetProcAddress( - user32, "SetProcessDPIAware"); - if (SetProcessDPIAware) - SetProcessDPIAware(); - FreeLibrary(user32); + SetProcessDPIAware(); initRawInput(); m_lfstart = ::GetTickCount(); diff --git a/intern/ghost/intern/GHOST_WaylandCursorSettings.h b/intern/ghost/intern/GHOST_WaylandCursorSettings.h new file mode 100644 index 00000000000..c7d2d82ff84 --- /dev/null +++ b/intern/ghost/intern/GHOST_WaylandCursorSettings.h @@ -0,0 +1,130 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + */ + +#pragma once +#include <dbus/dbus.h> +#include <string> + +static DBusMessage *get_setting_sync(DBusConnection *const connection, + const char *key, + const char *value) +{ + DBusError error; + dbus_bool_t success; + DBusMessage *message; + DBusMessage *reply; + + dbus_error_init(&error); + + message = dbus_message_new_method_call("org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.Settings", + "Read"); + + success = dbus_message_append_args( + message, DBUS_TYPE_STRING, &key, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID); + + if (!success) { + return NULL; + } + + reply = dbus_connection_send_with_reply_and_block( + connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error); + + dbus_message_unref(message); + + if (dbus_error_is_set(&error)) { + return NULL; + } + + return reply; +} + +static bool parse_type(DBusMessage *const reply, const int type, void *value) +{ + DBusMessageIter iter[3]; + + dbus_message_iter_init(reply, &iter[0]); + if (dbus_message_iter_get_arg_type(&iter[0]) != DBUS_TYPE_VARIANT) { + return false; + } + + dbus_message_iter_recurse(&iter[0], &iter[1]); + if (dbus_message_iter_get_arg_type(&iter[1]) != DBUS_TYPE_VARIANT) { + return false; + } + + dbus_message_iter_recurse(&iter[1], &iter[2]); + if (dbus_message_iter_get_arg_type(&iter[2]) != type) { + return false; + } + + dbus_message_iter_get_basic(&iter[2], value); + + return true; +} + +static bool get_cursor_settings(std::string &theme, int &size) +{ + static const char name[] = "org.gnome.desktop.interface"; + static const char key_theme[] = "cursor-theme"; + static const char key_size[] = "cursor-size"; + + DBusError error; + DBusConnection *connection; + DBusMessage *reply; + const char *value_theme = NULL; + + dbus_error_init(&error); + + connection = dbus_bus_get(DBUS_BUS_SESSION, &error); + + if (dbus_error_is_set(&error)) { + return false; + } + + reply = get_setting_sync(connection, name, key_theme); + if (!reply) { + return false; + } + + if (!parse_type(reply, DBUS_TYPE_STRING, &value_theme)) { + dbus_message_unref(reply); + return false; + } + + theme = std::string(value_theme); + + dbus_message_unref(reply); + + reply = get_setting_sync(connection, name, key_size); + if (!reply) { + return false; + } + + if (!parse_type(reply, DBUS_TYPE_INT32, &size)) { + dbus_message_unref(reply); + return false; + } + + dbus_message_unref(reply); + + return true; +} diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 1e1d0814d3a..cbac2d6eaa1 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -29,11 +29,19 @@ #include <wayland-egl.h> +static constexpr size_t base_dpi = 96; + struct window_t { GHOST_WindowWayland *w; wl_surface *surface; + // outputs on which the window is currently shown on + std::unordered_set<const output_t *> outputs; + GHOST_TUns16 dpi = 0; + int scale = 1; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; + struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr; + enum zxdg_toplevel_decoration_v1_mode decoration_mode; wl_egl_window *egl_window; int32_t pending_width, pending_height; bool is_maximised; @@ -93,17 +101,30 @@ static const xdg_toplevel_listener toplevel_listener = { toplevel_close, }; +static void toplevel_decoration_configure( + void *data, + struct zxdg_toplevel_decoration_v1 * /*zxdg_toplevel_decoration_v1*/, + uint32_t mode) +{ + static_cast<window_t *>(data)->decoration_mode = zxdg_toplevel_decoration_v1_mode(mode); +} + +static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = { + toplevel_decoration_configure, +}; + static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial) { window_t *win = static_cast<window_t *>(data); - int w, h; - wl_egl_window_get_attached_size(win->egl_window, &w, &h); - if (win->pending_width != 0 && win->pending_height != 0 && win->pending_width != w && - win->pending_height != h) { - win->width = win->pending_width; - win->height = win->pending_height; - wl_egl_window_resize(win->egl_window, win->pending_width, win->pending_height, 0, 0); + if (win->xdg_surface != xdg_surface) { + return; + } + + if (win->pending_width != 0 && win->pending_height != 0) { + win->width = win->scale * win->pending_width; + win->height = win->scale * win->pending_height; + wl_egl_window_resize(win->egl_window, win->width, win->height, 0, 0); win->pending_width = 0; win->pending_height = 0; win->w->notify_size(); @@ -123,6 +144,52 @@ static const xdg_surface_listener surface_listener = { surface_configure, }; +static bool update_scale(GHOST_WindowWayland *window) +{ + int scale = 0; + for (const output_t *output : window->outputs_active()) { + if (output->scale > scale) + scale = output->scale; + } + + if (scale > 0 && window->scale() != scale) { + window->scale() = scale; + // using the real DPI will cause wrong scaling of the UI + // use a multiplier for the default DPI as workaround + window->dpi() = scale * base_dpi; + wl_surface_set_buffer_scale(window->surface(), scale); + return true; + } + return false; +} + +static void surface_enter(void *data, struct wl_surface * /*wl_surface*/, struct wl_output *output) +{ + GHOST_WindowWayland *w = static_cast<GHOST_WindowWayland *>(data); + for (const output_t *reg_output : w->outputs()) { + if (reg_output->output == output) { + w->outputs_active().insert(reg_output); + } + } + update_scale(w); +} + +static void surface_leave(void *data, struct wl_surface * /*wl_surface*/, struct wl_output *output) +{ + GHOST_WindowWayland *w = static_cast<GHOST_WindowWayland *>(data); + for (const output_t *reg_output : w->outputs()) { + if (reg_output->output == output) { + w->outputs_active().erase(reg_output); + } + } + update_scale(w); +} + +struct wl_surface_listener wl_surface_listener = { + surface_enter, + surface_leave, +}; + /** \} */ /* -------------------------------------------------------------------- */ @@ -161,17 +228,28 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, /* Window surfaces. */ w->surface = wl_compositor_create_surface(m_system->compositor()); + wl_surface_add_listener(w->surface, &wl_surface_listener, this); + w->egl_window = wl_egl_window_create(w->surface, int(width), int(height)); w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface); w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface); + if (m_system->decoration_manager()) { + w->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + m_system->decoration_manager(), w->xdg_toplevel); + zxdg_toplevel_decoration_v1_add_listener( + w->xdg_toplevel_decoration, &toplevel_decoration_v1_listener, w); + zxdg_toplevel_decoration_v1_set_mode(w->xdg_toplevel_decoration, + ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } + wl_surface_set_user_data(w->surface, this); xdg_surface_add_listener(w->xdg_surface, &surface_listener, w); xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w); - if (parentWindow) { + if (parentWindow && is_dialog) { xdg_toplevel_set_parent( w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel); } @@ -192,6 +270,9 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, if (setDrawingContextType(type) == GHOST_kFailure) { GHOST_PRINT("Failed to create EGL context" << std::endl); } + + /* set swap interval to 0 to prevent blocking */ + setSwapInterval(0); } GHOST_TSuccess GHOST_WindowWayland::close() @@ -226,6 +307,31 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size() new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this)); } +wl_surface *GHOST_WindowWayland::surface() const +{ + return w->surface; +} + +const std::vector<output_t *> &GHOST_WindowWayland::outputs() const +{ + return m_system->outputs(); +} + +std::unordered_set<const output_t *> &GHOST_WindowWayland::outputs_active() +{ + return w->outputs; +} + +uint16_t &GHOST_WindowWayland::dpi() +{ + return w->dpi; +} + +int &GHOST_WindowWayland::scale() +{ + return w->scale; +} + GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode) { return m_system->setCursorGrab(mode, w->surface); @@ -310,6 +416,9 @@ GHOST_WindowWayland::~GHOST_WindowWayland() releaseNativeHandles(); wl_egl_window_destroy(w->egl_window); + if (w->xdg_toplevel_decoration) { + zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration); + } xdg_toplevel_destroy(w->xdg_toplevel); xdg_surface_destroy(w->xdg_surface); wl_surface_destroy(w->surface); @@ -317,6 +426,11 @@ GHOST_WindowWayland::~GHOST_WindowWayland() delete w; } +GHOST_TUns16 GHOST_WindowWayland::getDPIHint() +{ + return w->dpi; +} + GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) { return m_system->setCursorVisibility(visible); diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index b62b5c24d60..dbddc7c469e 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -24,9 +24,14 @@ #include "GHOST_Window.h" +#include <unordered_set> +#include <vector> + class GHOST_SystemWayland; struct window_t; +struct wl_surface; +struct output_t; class GHOST_WindowWayland : public GHOST_Window { public: @@ -47,6 +52,8 @@ class GHOST_WindowWayland : public GHOST_Window { ~GHOST_WindowWayland() override; + GHOST_TUns16 getDPIHint() override; + GHOST_TSuccess close(); GHOST_TSuccess activate(); @@ -55,6 +62,16 @@ class GHOST_WindowWayland : public GHOST_Window { GHOST_TSuccess notify_size(); + wl_surface *surface() const; + + const std::vector<output_t *> &outputs() const; + + std::unordered_set<const output_t *> &outputs_active(); + + uint16_t &dpi(); + + int &scale(); + protected: GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index bf142239606..eeafe333633 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -84,9 +84,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_wantAlphaBackground(alphaBackground), m_normal_state(GHOST_kWindowStateNormal), m_user32(NULL), - m_fpGetPointerInfoHistory(NULL), - m_fpGetPointerPenInfoHistory(NULL), - m_fpGetPointerTouchInfoHistory(NULL), m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP), m_debug_context(is_debug) { @@ -121,19 +118,21 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, monitor.dwFlags = 0; GetMonitorInfo(MonitorFromRect(&win_rect, MONITOR_DEFAULTTONEAREST), &monitor); - /* Constrain size to fit within this monitor. */ + /* Constrain requested size and position to fit within this monitor. */ width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect.right - win_rect.left); height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect.bottom - win_rect.top); - win_rect.left = min(max(monitor.rcWork.left, win_rect.left), monitor.rcWork.right - width); win_rect.right = win_rect.left + width; win_rect.top = min(max(monitor.rcWork.top, win_rect.top), monitor.rcWork.bottom - height); win_rect.bottom = win_rect.top + height; - /* Adjust our requested values to allow for caption, borders, shadows, etc. - Windows API Note: You cannot specify WS_OVERLAPPED when calling. */ + /* Adjust to allow for caption, borders, shadows, scaling, etc. Resulting values can be + * correctly outside of monitor bounds. Note: You cannot specify WS_OVERLAPPED when calling. */ AdjustWindowRectEx(&win_rect, style & ~WS_OVERLAPPED, FALSE, extended_style); + /* But never allow a top position that can hide part of the title bar. */ + win_rect.top = max(monitor.rcWork.top, win_rect.top); + m_hWnd = ::CreateWindowExW(extended_style, // window extended style s_windowClassName, // pointer to registered class name title_16, // pointer to window name @@ -151,19 +150,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_user32 = ::LoadLibrary("user32.dll"); if (m_hWnd) { - if (m_user32) { - // Touch enabled screens with pen support by default have gestures - // enabled, which results in a delay between the pointer down event - // and the first move when using the stylus. RegisterTouchWindow - // disables the new gesture architecture enabling the events to be - // sent immediately to the application rather than being absorbed by - // the gesture API. - GHOST_WIN32_RegisterTouchWindow pRegisterTouchWindow = (GHOST_WIN32_RegisterTouchWindow) - GetProcAddress(m_user32, "RegisterTouchWindow"); - if (pRegisterTouchWindow) { - pRegisterTouchWindow(m_hWnd, 0); - } - } + RegisterTouchWindow(m_hWnd, 0); // Register this window as a droptarget. Requires m_hWnd to be valid. // Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32. @@ -230,16 +217,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } } - // Initialize Windows Ink - if (m_user32) { - m_fpGetPointerInfoHistory = (GHOST_WIN32_GetPointerInfoHistory)::GetProcAddress( - m_user32, "GetPointerInfoHistory"); - m_fpGetPointerPenInfoHistory = (GHOST_WIN32_GetPointerPenInfoHistory)::GetProcAddress( - m_user32, "GetPointerPenInfoHistory"); - m_fpGetPointerTouchInfoHistory = (GHOST_WIN32_GetPointerTouchInfoHistory)::GetProcAddress( - m_user32, "GetPointerTouchInfoHistory"); - } - // Initialize Wintab m_wintab.handle = ::LoadLibrary("Wintab32.dll"); if (m_wintab.handle && m_system->getTabletAPI() != GHOST_kTabletNative) { @@ -324,9 +301,6 @@ GHOST_WindowWin32::~GHOST_WindowWin32() if (m_user32) { FreeLibrary(m_user32); m_user32 = NULL; - m_fpGetPointerInfoHistory = NULL; - m_fpGetPointerPenInfoHistory = NULL; - m_fpGetPointerTouchInfoHistory = NULL; } if (m_customCursor) { @@ -948,15 +922,14 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem(); GHOST_TUns32 outCount; - if (!(m_fpGetPointerInfoHistory && m_fpGetPointerInfoHistory(pointerId, &outCount, NULL))) { + if (!(GetPointerInfoHistory(pointerId, &outCount, NULL))) { return GHOST_kFailure; } auto pointerPenInfo = std::vector<POINTER_PEN_INFO>(outCount); outPointerInfo.resize(outCount); - if (!(m_fpGetPointerPenInfoHistory && - m_fpGetPointerPenInfoHistory(pointerId, &outCount, pointerPenInfo.data()))) { + if (!(GetPointerPenInfoHistory(pointerId, &outCount, pointerPenInfo.data()))) { return GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index b004f7e7b19..a13bd876667 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -53,177 +53,12 @@ typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID); typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL); typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL); -// typedef to user32 functions to disable gestures on windows -typedef BOOL(API *GHOST_WIN32_RegisterTouchWindow)(HWND hwnd, ULONG ulFlags); - // typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND); #ifndef USER_DEFAULT_SCREEN_DPI # define USER_DEFAULT_SCREEN_DPI 96 #endif // USER_DEFAULT_SCREEN_DPI -// typedefs for user32 functions to allow pointer functions -enum tagPOINTER_INPUT_TYPE { - PT_POINTER = 1, // Generic pointer - PT_TOUCH = 2, // Touch - PT_PEN = 3, // Pen - PT_MOUSE = 4, // Mouse -#if (WINVER >= 0x0603) - PT_TOUCHPAD = 5, // Touchpad -#endif /* WINVER >= 0x0603 */ -}; - -typedef enum tagPOINTER_BUTTON_CHANGE_TYPE { - POINTER_CHANGE_NONE, - POINTER_CHANGE_FIRSTBUTTON_DOWN, - POINTER_CHANGE_FIRSTBUTTON_UP, - POINTER_CHANGE_SECONDBUTTON_DOWN, - POINTER_CHANGE_SECONDBUTTON_UP, - POINTER_CHANGE_THIRDBUTTON_DOWN, - POINTER_CHANGE_THIRDBUTTON_UP, - POINTER_CHANGE_FOURTHBUTTON_DOWN, - POINTER_CHANGE_FOURTHBUTTON_UP, - POINTER_CHANGE_FIFTHBUTTON_DOWN, - POINTER_CHANGE_FIFTHBUTTON_UP, -} POINTER_BUTTON_CHANGE_TYPE; - -typedef DWORD POINTER_INPUT_TYPE; -typedef UINT32 POINTER_FLAGS; - -#define POINTER_FLAG_NONE 0x00000000 -#define POINTER_FLAG_NEW 0x00000001 -#define POINTER_FLAG_INRANGE 0x00000002 -#define POINTER_FLAG_INCONTACT 0x00000004 -#define POINTER_FLAG_FIRSTBUTTON 0x00000010 -#define POINTER_FLAG_SECONDBUTTON 0x00000020 -#define POINTER_FLAG_THIRDBUTTON 0x00000040 -#define POINTER_FLAG_FOURTHBUTTON 0x00000080 -#define POINTER_FLAG_FIFTHBUTTON 0x00000100 -#define POINTER_FLAG_PRIMARY 0x00002000 -#define POINTER_FLAG_CONFIDENCE 0x000004000 -#define POINTER_FLAG_CANCELED 0x000008000 -#define POINTER_FLAG_DOWN 0x00010000 -#define POINTER_FLAG_UPDATE 0x00020000 -#define POINTER_FLAG_UP 0x00040000 -#define POINTER_FLAG_WHEEL 0x00080000 -#define POINTER_FLAG_HWHEEL 0x00100000 -#define POINTER_FLAG_CAPTURECHANGED 0x00200000 -#define POINTER_FLAG_HASTRANSFORM 0x00400000 - -typedef struct tagPOINTER_INFO { - POINTER_INPUT_TYPE pointerType; - UINT32 pointerId; - UINT32 frameId; - POINTER_FLAGS pointerFlags; - HANDLE sourceDevice; - HWND hwndTarget; - POINT ptPixelLocation; - POINT ptHimetricLocation; - POINT ptPixelLocationRaw; - POINT ptHimetricLocationRaw; - DWORD dwTime; - UINT32 historyCount; - INT32 InputData; - DWORD dwKeyStates; - UINT64 PerformanceCount; - POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; -} POINTER_INFO; - -typedef UINT32 PEN_FLAGS; -#define PEN_FLAG_NONE 0x00000000 // Default -#define PEN_FLAG_BARREL 0x00000001 // The barrel button is pressed -#define PEN_FLAG_INVERTED 0x00000002 // The pen is inverted -#define PEN_FLAG_ERASER 0x00000004 // The eraser button is pressed - -typedef UINT32 PEN_MASK; -#define PEN_MASK_NONE 0x00000000 // Default - none of the optional fields are valid -#define PEN_MASK_PRESSURE 0x00000001 // The pressure field is valid -#define PEN_MASK_ROTATION 0x00000002 // The rotation field is valid -#define PEN_MASK_TILT_X 0x00000004 // The tiltX field is valid -#define PEN_MASK_TILT_Y 0x00000008 // The tiltY field is valid - -typedef struct tagPOINTER_PEN_INFO { - POINTER_INFO pointerInfo; - PEN_FLAGS penFlags; - PEN_MASK penMask; - UINT32 pressure; - UINT32 rotation; - INT32 tiltX; - INT32 tiltY; -} POINTER_PEN_INFO; - -/* - * Flags that appear in pointer input message parameters - */ -#define POINTER_MESSAGE_FLAG_NEW 0x00000001 // New pointer -#define POINTER_MESSAGE_FLAG_INRANGE 0x00000002 // Pointer has not departed -#define POINTER_MESSAGE_FLAG_INCONTACT 0x00000004 // Pointer is in contact -#define POINTER_MESSAGE_FLAG_FIRSTBUTTON 0x00000010 // Primary action -#define POINTER_MESSAGE_FLAG_SECONDBUTTON 0x00000020 // Secondary action -#define POINTER_MESSAGE_FLAG_THIRDBUTTON 0x00000040 // Third button -#define POINTER_MESSAGE_FLAG_FOURTHBUTTON 0x00000080 // Fourth button -#define POINTER_MESSAGE_FLAG_FIFTHBUTTON 0x00000100 // Fifth button -#define POINTER_MESSAGE_FLAG_PRIMARY 0x00002000 // Pointer is primary -#define POINTER_MESSAGE_FLAG_CONFIDENCE \ - 0x00004000 // Pointer is considered unlikely to be accidental -#define POINTER_MESSAGE_FLAG_CANCELED 0x00008000 // Pointer is departing in an abnormal manner - -typedef UINT32 TOUCH_FLAGS; -#define TOUCH_FLAG_NONE 0x00000000 // Default - -typedef UINT32 TOUCH_MASK; -#define TOUCH_MASK_NONE 0x00000000 // Default - none of the optional fields are valid -#define TOUCH_MASK_CONTACTAREA 0x00000001 // The rcContact field is valid -#define TOUCH_MASK_ORIENTATION 0x00000002 // The orientation field is valid -#define TOUCH_MASK_PRESSURE 0x00000004 // The pressure field is valid - -typedef struct tagPOINTER_TOUCH_INFO { - POINTER_INFO pointerInfo; - TOUCH_FLAGS touchFlags; - TOUCH_MASK touchMask; - RECT rcContact; - RECT rcContactRaw; - UINT32 orientation; - UINT32 pressure; -} POINTER_TOUCH_INFO; - -/* - * Macros to retrieve information from pointer input message parameters - */ -#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) -#define IS_POINTER_FLAG_SET_WPARAM(wParam, flag) (((DWORD)HIWORD(wParam) & (flag)) == (flag)) -#define IS_POINTER_NEW_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_NEW) -#define IS_POINTER_INRANGE_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_INRANGE) -#define IS_POINTER_INCONTACT_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_INCONTACT) -#define IS_POINTER_FIRSTBUTTON_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIRSTBUTTON) -#define IS_POINTER_SECONDBUTTON_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_SECONDBUTTON) -#define IS_POINTER_THIRDBUTTON_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_THIRDBUTTON) -#define IS_POINTER_FOURTHBUTTON_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FOURTHBUTTON) -#define IS_POINTER_FIFTHBUTTON_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIFTHBUTTON) -#define IS_POINTER_PRIMARY_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_PRIMARY) -#define HAS_POINTER_CONFIDENCE_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_CONFIDENCE) -#define IS_POINTER_CANCELED_WPARAM(wParam) \ - IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_CANCELED) - -typedef BOOL(WINAPI *GHOST_WIN32_GetPointerInfoHistory)(UINT32 pointerId, - UINT32 *entriesCount, - POINTER_INFO *pointerInfo); -typedef BOOL(WINAPI *GHOST_WIN32_GetPointerPenInfoHistory)(UINT32 pointerId, - UINT32 *entriesCount, - POINTER_PEN_INFO *penInfo); -typedef BOOL(WINAPI *GHOST_WIN32_GetPointerTouchInfoHistory)(UINT32 pointerId, - UINT32 *entriesCount, - POINTER_TOUCH_INFO *touchInfo); - struct GHOST_PointerInfoWin32 { GHOST_TInt32 pointerId; GHOST_TInt32 isPrimary; @@ -576,9 +411,6 @@ class GHOST_WindowWin32 : public GHOST_Window { /** `user32.dll` handle */ HMODULE m_user32; - GHOST_WIN32_GetPointerInfoHistory m_fpGetPointerInfoHistory; - GHOST_WIN32_GetPointerPenInfoHistory m_fpGetPointerPenInfoHistory; - GHOST_WIN32_GetPointerTouchInfoHistory m_fpGetPointerTouchInfoHistory; HWND m_parentWindowHwnd; |