We rely on AppKit-internal events to know when a window is being
dragged. In Catalina, AppKit stopped sending the "drag ended" event when
no drag actually took place, though it still sends "drag started" events
when the title bar is clicked. Ironically, this caused us to think the
window was still being dragged. In that case, waiting for the mouse
button to come back up should allow us to determine when the drag should
end.
Signed-off-by: Chip Davis <cdavis@codeweavers.com>
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
App Nap defers timer firings and I/O if the app is not visibly or audibly
updating. An app is supposed to disable it during user-requested or background
activity, but we can't know when the Windows app is engaged in such. Since it's
not generally acceptable for timers or IO to be deferred, we have to disable it
at all times.
The user can re-enable it by setting the following registry setting:
[HKEY\Software\Wine\Mac Driver]
"EnableAppNap"="y"
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
It had only been done when a window is shown. Some games change the display
mode before showing their first window. Following Mac conventions, the Mac
driver does not apply display mode changes when it's not the active GUI app.
If such a game were to change the mode and then query display-mode-related info,
it would get info for the original mode, not the requested mode.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
When they were always 32x32, treating that size as though it were in Cocoa's
virtual "points" rather than pixels produced good results even though it wasn't
really correct.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
In particular, when an input method for an Asian language (e.g. Pinyin) is
selected, we were getting repeated notifications. Querying the selected input
method upon receiving them suggested that the keyboard layout changed to U.S.
then back to Pinyin, then several redundant notifications with no apparent
change.
Since the handler for the posted KEYBOARD_CHANGED events sends WM_CANCELMODE to
the active window, this was having bad effects.
The spurious notifications can be distinguished by there being no current
text input context or client. To detect redundant notifications, we track the
last keyboard input source and keyboard layout input source and compare with
the new ones to see if they really changed.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
It doesn't seem to work well. In full-screen mode, newly-added windows don't
always properly resize to fill the screen, so they're not the same size as the
windows they're nominally tabbed with. In non-full-screen mode, switching
between tabs sometimes causes the windows to grow in height each time. Etc.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Cocoa does this automatically for non-owned windows and informs the back end
via a different mechanism (WINDOW_BROUGHT_FORWARD). However, for owned windows
(child windows in Cocoa parlance), Cocoa does not change their z-order relative
to the owner (parent) or sibling owned windows when clicked. So, we have to
move the window in user32's z-order so that it gets moved appropriately on
screen in response.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
-[NSApplication sendEvent:] seems to consume the event and doesn't pass it along
to the window.
Mac keyboards haven't included a Help key for a long time, but users with PC
keyboards can use the Insert key, which is in the same position. The Mac
driver translates either one to VK_INSERT.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
If another app grabbed the clipboard, that most likely happened while it was
active and the Wine process was inactive. Our process being made active again
is a good opportunity to check for that.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
When windows aren't full-screen, non-floating windows go in NSNormalWindowLevel
and floating ones go in NSFloatingWindowLevel, which is higher. However, a
non-floating full-screen window will go into a level higher than either of
those. The prior logic of the -adjustWindowLevels: method would keep the
floating windows at a window level at least that high. They should actually
be in a strictly higher level.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
It would eventually get updated by the keyboard changed event, but
only after the message queue was pumped.
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
When this Retina mode is enabled and the primary display is in the user's
default configuration, Wine gets told that screen and window sizes and mouse
coordinates are twice what Cocoa reports them as in its virtual coordinate
system ("points"). The Windows apps then renders at that high resolution and
the Mac driver blits it to screen. If the screen is actually a Retina display
in a high-DPI mode, then this extra detail will be preserved. Otherwise, the
rendering will be downsampled and blurry.
This is intended to be combined with increasing the Windows DPI, as via winecfg.
If that is doubled to 192, then, in theory, graphical elements will remain the
same visual size on screen but be rendered with finer detail. Unfortunately,
many Windows programs don't correctly handle non-standard DPI so the results
are not always perfect.
The registry setting to enable Retina mode is:
[HKEY_CURRENT_USER\Software\Wine\Mac Driver]
"RetinaMode"="y"
Note that this setting is not looked for in the AppDefaults\<exe name> key
because it doesn't make sense for only some processes in a Wine session to see
the high-resolution sizes and coordinates.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This is so negative coordinates are adjusted in the same direction as
positive ones (left and up).
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Cocoa manages an autorelease pool on the main thread, but it only drains it
when it processes an event. Our requests come through a run loop source, which
doesn't count as an event. So, autoreleased objects can accumulate when the
app is not being interacted with.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Commit 793ab7d45 fixed a bug where WINDOW_BROUGHT_FORWARD events weren't being
posted when they should, but it caused a regression in Scribblenauts Unlimited.
Every click caused a window ordering operation that generated messages and
Scribblenauts would move the mouse cursor to the upper-left corner of the
window in response.
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Not sending the brought-forward event for a click that was sent was an artifact
of a time when that branch was only used for posting a request for focus. When
I added the brought-forward event, I didn't reconsider that logic.
OS X doesn't have the same concept of maximized windows as Windows does.
There's no mode that prevents a normally-movable window from being moved. If
a window is "zoomed", it mostly fills the screen but the user can still move
or resize it, at which point it ceases to be in the zoomed state. So, users
are confused and frustrated when they can't move a window that's maximized.
To get similar behavior while still respecting Win32 semantics, we detect when
the user tries to move a maximized window. When they start, a request is
submitted to the app to restore the window. Unless and until the window is
restored, we don't actually allow the window to move.
The user expects to move the window from its current (maximized) position. It
should not jump to its normal position upon being restored. So, we set the
window's normal position to its current position before restoring it.
When a window is being dragged, we prevent delivery of clicks to Wine. We were
also preventing telling Wine that a window had been brought forward, but this
was incorrect. It prevented clicks in the title bar from activating the window.
If the mouse is captured, we change which window receives the click event, but
that shouldn't change which window we tell Wine was brought forward by Cocoa.
We can't prevent Cocoa from bringing disabled/no-activate windows forward. So,
we need to tell Wine about the z-order change.
We still do avoid telling Wine to activate disabled/no-activate windows, though.
The Mac driver can generate scroll wheel events with values which are not integral
multiples of WHEEL_DELTA. Apps should handle that by scrolling a corresponding
non-integral multiple of what they'd do for a WHEEL_DELTA-valued scroll or, if
they can't, then at least accumulate scroll distance until its magnitude exceeds
WHEEL_DELTA and do a "chunky" scroll. However, many apps don't do that properly.
They may scroll way too far/fast or even in the opposite direction.
If the registry setting UsePreciseScrolling is set to "n", the Mac driver will do
that accumulation and chunking itself to work around such broken app behavior.
Cocoa will bring an unowned window to the front of its level when it's clicked,
but it doesn't do that for owned windows. The old code went out of its way to
make owned windows behave like unowned windows in this respect. That was
exactly backward. We wish we could control whether windows are raised on a
click. We don't have that opportunity for unowned windows, but, by ripping
out a bunch of code, we do for owned windows.
Many games clip the cursor to the client area of the window. However, on OS X,
the resizing controls extend into that client area. So, it's possible that
while playing, the user might unintentionally click in the resizing area and
drag, resizing the window.
We only care if we have changed the mode and we're changing it back to its
original. Even if the current mode matches the target mode, we may still
need to release the displays and clear the entry from originalDisplayModes.
originalDisplayModes should be used when active, empty when inactive.
latentDisplayModes is used when inactive, empty when active.
The count of entries in originalDisplayModes is used to test whether the
process has the displays captured so adding entries when inactive would give
incorrect results. This could have led us to mistakenly change the display
mode when we don't have the displays captured.
Among other things, this fixes Syberia 2. That game shows, hides, and then
shows its window. Hiding it caused a WINDOW_LOST_FOCUS event to be queued.
By the time it was processed, the window was the foreground window again.
In response to being told it had lost focus, the game minimized its window.
Hiding the window should have prevented or discarded the WINDOW_LOST_FOCUS
event since the change was driven from Wine and the Win32 foreground/active
window state would already be correct. In addition, when the program
re-showed its window and made it foreground, that should have discarded the
event as being out of date. Now they do.
Fixes a problem in some games which repeatedly (re)establish the same cursor
clipping rect, making it exceedingly difficult to move the camera with the
mouse.
This simulates some of what would happen if user32 were managing the drag. The
click in the caption would cause WM_SYSCOMMAND/SC_MOVE. The processing of that
message is synchronous and doesn't return until the move is complete.
Some games require that "blocking" in the internal event loop to prevent them
from misbehaving during the drag.
The tracking of whether it is over a window or not is only updated when the
mouse moves. If a window was created or moved under it, then the state can be
stale. That caused us to defer hiding the cursor until the mouse was moved.
This happens at the start of games pretty often.
The code had previously set the cursor back to the standard arrow and unhid
it when it left all app windows. Now it restores the cursor image that the
app set and re-hides it if necessary when it moves back over any app window.