winemac: Implement ChangeDisplaySettingsEx().
This commit is contained in:
parent
4f4ac0cafc
commit
d26a6bf451
|
@ -48,11 +48,14 @@ @interface WineApplication : NSApplication <NSApplicationDelegate>
|
|||
BOOL primaryScreenHeightValid;
|
||||
|
||||
NSMutableArray* orderedWineWindows;
|
||||
|
||||
NSMutableDictionary* originalDisplayModes;
|
||||
}
|
||||
|
||||
@property (nonatomic) CGEventSourceKeyboardType keyboardType;
|
||||
@property (readonly, copy, nonatomic) NSEvent* lastFlagsChanged;
|
||||
@property (readonly, nonatomic) NSArray* orderedWineWindows;
|
||||
@property (readonly, nonatomic) BOOL areDisplaysCaptured;
|
||||
|
||||
- (void) transformProcessToForeground;
|
||||
|
||||
|
|
|
@ -51,7 +51,10 @@ - (id) init
|
|||
keyWindows = [[NSMutableArray alloc] init];
|
||||
orderedWineWindows = [[NSMutableArray alloc] init];
|
||||
|
||||
if (!eventQueues || !eventQueuesLock || !keyWindows || !orderedWineWindows)
|
||||
originalDisplayModes = [[NSMutableDictionary alloc] init];
|
||||
|
||||
if (!eventQueues || !eventQueuesLock || !keyWindows || !orderedWineWindows ||
|
||||
!originalDisplayModes)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
|
@ -62,6 +65,7 @@ - (id) init
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
[originalDisplayModes release];
|
||||
[orderedWineWindows release];
|
||||
[keyWindows release];
|
||||
[eventQueues release];
|
||||
|
@ -312,13 +316,14 @@ - (void) wineWindow:(WineWindow*)window
|
|||
}
|
||||
}
|
||||
|
||||
- (void) sendDisplaysChanged
|
||||
- (void) sendDisplaysChanged:(BOOL)activating
|
||||
{
|
||||
macdrv_event event;
|
||||
WineEventQueue* queue;
|
||||
|
||||
event.type = DISPLAYS_CHANGED;
|
||||
event.window = NULL;
|
||||
event.displays_changed.activating = activating;
|
||||
|
||||
[eventQueuesLock lock];
|
||||
for (queue in eventQueues)
|
||||
|
@ -326,6 +331,135 @@ - (void) sendDisplaysChanged
|
|||
[eventQueuesLock unlock];
|
||||
}
|
||||
|
||||
// We can compare two modes directly using CFEqual, but that may require that
|
||||
// they are identical to a level that we don't need. In particular, when the
|
||||
// OS switches between the integrated and discrete GPUs, the set of display
|
||||
// modes can change in subtle ways. We're interested in whether two modes
|
||||
// match in their most salient features, even if they aren't identical.
|
||||
- (BOOL) mode:(CGDisplayModeRef)mode1 matchesMode:(CGDisplayModeRef)mode2
|
||||
{
|
||||
NSString *encoding1, *encoding2;
|
||||
uint32_t ioflags1, ioflags2, different;
|
||||
double refresh1, refresh2;
|
||||
|
||||
if (CGDisplayModeGetWidth(mode1) != CGDisplayModeGetWidth(mode2)) return FALSE;
|
||||
if (CGDisplayModeGetHeight(mode1) != CGDisplayModeGetHeight(mode2)) return FALSE;
|
||||
|
||||
encoding1 = [(NSString*)CGDisplayModeCopyPixelEncoding(mode1) autorelease];
|
||||
encoding2 = [(NSString*)CGDisplayModeCopyPixelEncoding(mode2) autorelease];
|
||||
if (![encoding1 isEqualToString:encoding2]) return FALSE;
|
||||
|
||||
ioflags1 = CGDisplayModeGetIOFlags(mode1);
|
||||
ioflags2 = CGDisplayModeGetIOFlags(mode2);
|
||||
different = ioflags1 ^ ioflags2;
|
||||
if (different & (kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeStretchedFlag |
|
||||
kDisplayModeInterlacedFlag | kDisplayModeTelevisionFlag))
|
||||
return FALSE;
|
||||
|
||||
refresh1 = CGDisplayModeGetRefreshRate(mode1);
|
||||
if (refresh1 == 0) refresh1 = 60;
|
||||
refresh2 = CGDisplayModeGetRefreshRate(mode2);
|
||||
if (refresh2 == 0) refresh2 = 60;
|
||||
if (fabs(refresh1 - refresh2) > 0.1) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (CGDisplayModeRef)modeMatchingMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID
|
||||
{
|
||||
CGDisplayModeRef ret = NULL;
|
||||
NSArray *modes = [(NSArray*)CGDisplayCopyAllDisplayModes(displayID, NULL) autorelease];
|
||||
for (id candidateModeObject in modes)
|
||||
{
|
||||
CGDisplayModeRef candidateMode = (CGDisplayModeRef)candidateModeObject;
|
||||
if ([self mode:candidateMode matchesMode:mode])
|
||||
{
|
||||
ret = candidateMode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (BOOL) setMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
NSNumber* displayIDKey = [NSNumber numberWithUnsignedInt:displayID];
|
||||
CGDisplayModeRef currentMode, originalMode;
|
||||
|
||||
currentMode = CGDisplayCopyDisplayMode(displayID);
|
||||
if (!currentMode) // Invalid display ID
|
||||
return FALSE;
|
||||
|
||||
if ([self mode:mode matchesMode:currentMode]) // Already there!
|
||||
{
|
||||
CGDisplayModeRelease(currentMode);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mode = [self modeMatchingMode:mode forDisplay:displayID];
|
||||
if (!mode)
|
||||
{
|
||||
CGDisplayModeRelease(currentMode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
originalMode = (CGDisplayModeRef)[originalDisplayModes objectForKey:displayIDKey];
|
||||
if (!originalMode)
|
||||
originalMode = currentMode;
|
||||
|
||||
if ([self mode:mode matchesMode:originalMode])
|
||||
{
|
||||
if ([originalDisplayModes count] == 1) // If this is the last changed display, do a blanket reset
|
||||
{
|
||||
CGRestorePermanentDisplayConfiguration();
|
||||
CGReleaseAllDisplays();
|
||||
[originalDisplayModes removeAllObjects];
|
||||
ret = TRUE;
|
||||
}
|
||||
else // ... otherwise, try to restore just the one display
|
||||
{
|
||||
if (CGDisplaySetDisplayMode(displayID, mode, NULL) == CGDisplayNoErr)
|
||||
{
|
||||
[originalDisplayModes removeObjectForKey:displayIDKey];
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([originalDisplayModes count] || CGCaptureAllDisplays() == CGDisplayNoErr)
|
||||
{
|
||||
if (CGDisplaySetDisplayMode(displayID, mode, NULL) == CGDisplayNoErr)
|
||||
{
|
||||
[originalDisplayModes setObject:(id)originalMode forKey:displayIDKey];
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (![originalDisplayModes count])
|
||||
{
|
||||
CGRestorePermanentDisplayConfiguration();
|
||||
CGReleaseAllDisplays();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGDisplayModeRelease(currentMode);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
[orderedWineWindows enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
|
||||
[(WineWindow*)obj adjustWindowLevel];
|
||||
}];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (BOOL) areDisplaysCaptured
|
||||
{
|
||||
return ([originalDisplayModes count] > 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ---------- NSApplication method overrides ----------
|
||||
|
@ -349,12 +483,24 @@ - (void)applicationDidBecomeActive:(NSNotification *)notification
|
|||
if ([window levelWhenActive] != [window level])
|
||||
[window setLevel:[window levelWhenActive]];
|
||||
}];
|
||||
|
||||
// If a Wine process terminates abruptly while it has the display captured
|
||||
// and switched to a different resolution, Mac OS X will uncapture the
|
||||
// displays and switch their resolutions back. However, the other Wine
|
||||
// processes won't have their notion of the desktop rect changed back.
|
||||
// This can lead them to refuse to draw or acknowledge clicks in certain
|
||||
// portions of their windows.
|
||||
//
|
||||
// To solve this, we synthesize a displays-changed event whenever we're
|
||||
// activated. This will provoke a re-synchronization of Wine's notion of
|
||||
// the desktop rect with the actual state.
|
||||
[self sendDisplaysChanged:TRUE];
|
||||
}
|
||||
|
||||
- (void)applicationDidChangeScreenParameters:(NSNotification *)notification
|
||||
{
|
||||
primaryScreenHeightValid = FALSE;
|
||||
[self sendDisplaysChanged];
|
||||
[self sendDisplaysChanged:FALSE];
|
||||
}
|
||||
|
||||
- (void)applicationDidResignActive:(NSNotification *)notification
|
||||
|
@ -512,3 +658,18 @@ void macdrv_beep(void)
|
|||
NSBeep();
|
||||
});
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_set_display_mode
|
||||
*/
|
||||
int macdrv_set_display_mode(const struct macdrv_display* display,
|
||||
CGDisplayModeRef display_mode)
|
||||
{
|
||||
__block int ret;
|
||||
|
||||
OnMainThread(^{
|
||||
ret = [NSApp setMode:display_mode forDisplay:display->displayID];
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -62,4 +62,6 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
@property (readonly, nonatomic) BOOL floating;
|
||||
@property (readonly, nonatomic) NSInteger levelWhenActive;
|
||||
|
||||
- (void) adjustWindowLevel;
|
||||
|
||||
@end
|
||||
|
|
|
@ -338,17 +338,22 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
|
|||
- (void) adjustWindowLevel
|
||||
{
|
||||
NSInteger level;
|
||||
BOOL fullscreen;
|
||||
BOOL fullscreen, captured;
|
||||
NSScreen* screen;
|
||||
NSUInteger index;
|
||||
WineWindow* other = nil;
|
||||
|
||||
screen = screen_covered_by_rect([self frame], [NSScreen screens]);
|
||||
fullscreen = (screen != nil);
|
||||
captured = (screen || [self screen]) && [NSApp areDisplaysCaptured];
|
||||
|
||||
if (fullscreen)
|
||||
if (captured || fullscreen)
|
||||
{
|
||||
if (captured)
|
||||
level = CGShieldingWindowLevel() + 1; /* Need +1 or we don't get mouse moves */
|
||||
else
|
||||
level = NSMainMenuWindowLevel + 1;
|
||||
|
||||
if (self.floating)
|
||||
level++;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,11 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(display);
|
||||
|
||||
|
||||
BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags);
|
||||
|
||||
|
||||
static CFArrayRef modes;
|
||||
static int default_mode_bpp;
|
||||
static CRITICAL_SECTION modes_section;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
{
|
||||
|
@ -117,6 +121,40 @@ static BOOL read_registry_settings(DEVMODEW *dm)
|
|||
}
|
||||
|
||||
|
||||
static BOOL write_registry_settings(const DEVMODEW *dm)
|
||||
{
|
||||
char wine_mac_reg_key[128];
|
||||
HKEY hkey;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (!get_display_device_reg_key(wine_mac_reg_key, sizeof(wine_mac_reg_key)))
|
||||
return FALSE;
|
||||
|
||||
if (RegCreateKeyExA(HKEY_CURRENT_CONFIG, wine_mac_reg_key, 0, NULL,
|
||||
REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL))
|
||||
return FALSE;
|
||||
|
||||
#define set_value(name, data) \
|
||||
if (RegSetValueExA(hkey, name, 0, REG_DWORD, (const BYTE*)(data), sizeof(DWORD))) \
|
||||
ret = FALSE
|
||||
|
||||
set_value("DefaultSettings.BitsPerPel", &dm->dmBitsPerPel);
|
||||
set_value("DefaultSettings.XResolution", &dm->dmPelsWidth);
|
||||
set_value("DefaultSettings.YResolution", &dm->dmPelsHeight);
|
||||
set_value("DefaultSettings.VRefresh", &dm->dmDisplayFrequency);
|
||||
set_value("DefaultSettings.Flags", &dm->dmDisplayFlags);
|
||||
set_value("DefaultSettings.XPanning", &dm->dmPosition.x);
|
||||
set_value("DefaultSettings.YPanning", &dm->dmPosition.y);
|
||||
set_value("DefaultSettings.Orientation", &dm->dmDisplayOrientation);
|
||||
set_value("DefaultSettings.FixedOutput", &dm->dmDisplayFixedOutput);
|
||||
|
||||
#undef set_value
|
||||
|
||||
RegCloseKey(hkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode)
|
||||
{
|
||||
CFStringRef pixel_encoding;
|
||||
|
@ -153,6 +191,202 @@ static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode)
|
|||
}
|
||||
|
||||
|
||||
static int get_default_bpp(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
EnterCriticalSection(&modes_section);
|
||||
|
||||
if (!default_mode_bpp)
|
||||
{
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
|
||||
if (mode)
|
||||
{
|
||||
default_mode_bpp = display_mode_bits_per_pixel(mode);
|
||||
CFRelease(mode);
|
||||
}
|
||||
|
||||
if (!default_mode_bpp)
|
||||
default_mode_bpp = 32;
|
||||
}
|
||||
|
||||
ret = default_mode_bpp;
|
||||
|
||||
LeaveCriticalSection(&modes_section);
|
||||
|
||||
TRACE(" -> %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ChangeDisplaySettingsEx (MACDRV.@)
|
||||
*
|
||||
*/
|
||||
LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
|
||||
HWND hwnd, DWORD flags, LPVOID lpvoid)
|
||||
{
|
||||
LONG ret = DISP_CHANGE_BADMODE;
|
||||
int bpp;
|
||||
DEVMODEW dm;
|
||||
BOOL def_mode = TRUE;
|
||||
struct macdrv_display *displays;
|
||||
int num_displays;
|
||||
CFArrayRef display_modes;
|
||||
CFIndex count, i, safe;
|
||||
|
||||
TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid);
|
||||
|
||||
if (devmode)
|
||||
{
|
||||
/* this is the minimal dmSize that XP accepts */
|
||||
if (devmode->dmSize < FIELD_OFFSET(DEVMODEW, dmFields))
|
||||
return DISP_CHANGE_FAILED;
|
||||
|
||||
if (devmode->dmSize >= FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(devmode->dmFields))
|
||||
{
|
||||
if (((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel) ||
|
||||
((devmode->dmFields & DM_PELSWIDTH) && devmode->dmPelsWidth) ||
|
||||
((devmode->dmFields & DM_PELSHEIGHT) && devmode->dmPelsHeight) ||
|
||||
((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency))
|
||||
def_mode = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (def_mode)
|
||||
{
|
||||
if (!macdrv_EnumDisplaySettingsEx(devname, ENUM_REGISTRY_SETTINGS, &dm, 0))
|
||||
{
|
||||
ERR("Default mode not found!\n");
|
||||
return DISP_CHANGE_BADMODE;
|
||||
}
|
||||
|
||||
TRACE("Return to original display mode\n");
|
||||
devmode = &dm;
|
||||
}
|
||||
|
||||
if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT))
|
||||
{
|
||||
WARN("devmode doesn't specify the resolution: %04x\n", devmode->dmFields);
|
||||
return DISP_CHANGE_BADMODE;
|
||||
}
|
||||
|
||||
if (macdrv_get_displays(&displays, &num_displays))
|
||||
return DISP_CHANGE_FAILED;
|
||||
|
||||
display_modes = CGDisplayCopyAllDisplayModes(displays[0].displayID, NULL);
|
||||
if (!display_modes)
|
||||
{
|
||||
macdrv_free_displays(displays);
|
||||
return DISP_CHANGE_FAILED;
|
||||
}
|
||||
|
||||
bpp = get_default_bpp();
|
||||
if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel != bpp)
|
||||
TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp, devmode->dmBitsPerPel);
|
||||
|
||||
TRACE("looking for %dx%dx%dbpp @%d Hz",
|
||||
(devmode->dmFields & DM_PELSWIDTH ? devmode->dmPelsWidth : 0),
|
||||
(devmode->dmFields & DM_PELSHEIGHT ? devmode->dmPelsHeight : 0),
|
||||
bpp,
|
||||
(devmode->dmFields & DM_DISPLAYFREQUENCY ? devmode->dmDisplayFrequency : 0));
|
||||
if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT)
|
||||
TRACE(" %sstretched", devmode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un");
|
||||
if (devmode->dmFields & DM_DISPLAYFLAGS)
|
||||
TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-");
|
||||
TRACE("\n");
|
||||
|
||||
safe = -1;
|
||||
count = CFArrayGetCount(display_modes);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
CGDisplayModeRef display_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(display_modes, i);
|
||||
uint32_t io_flags = CGDisplayModeGetIOFlags(display_mode);
|
||||
int mode_bpp = display_mode_bits_per_pixel(display_mode);
|
||||
size_t width = CGDisplayModeGetWidth(display_mode);
|
||||
size_t height = CGDisplayModeGetHeight(display_mode);
|
||||
|
||||
if (!(io_flags & kDisplayModeValidFlag) || !(io_flags & kDisplayModeSafeFlag))
|
||||
continue;
|
||||
|
||||
safe++;
|
||||
|
||||
if (bpp != mode_bpp)
|
||||
continue;
|
||||
|
||||
if (devmode->dmFields & DM_PELSWIDTH)
|
||||
{
|
||||
if (devmode->dmPelsWidth != width)
|
||||
continue;
|
||||
}
|
||||
if (devmode->dmFields & DM_PELSHEIGHT)
|
||||
{
|
||||
if (devmode->dmPelsHeight != height)
|
||||
continue;
|
||||
}
|
||||
if ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency != 0)
|
||||
{
|
||||
double refresh_rate = CGDisplayModeGetRefreshRate(display_mode);
|
||||
if (!refresh_rate)
|
||||
refresh_rate = 60;
|
||||
if (devmode->dmDisplayFrequency != (DWORD)refresh_rate)
|
||||
continue;
|
||||
}
|
||||
if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT)
|
||||
{
|
||||
if (!(devmode->dmDisplayFixedOutput == DMDFO_STRETCH) != !(io_flags & kDisplayModeStretchedFlag))
|
||||
continue;
|
||||
}
|
||||
if (devmode->dmFields & DM_DISPLAYFLAGS)
|
||||
{
|
||||
if (!(devmode->dmDisplayFlags & DM_INTERLACED) != !(io_flags & kDisplayModeInterlacedFlag))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we have a valid mode */
|
||||
TRACE("Requested display settings match mode %ld\n", safe);
|
||||
|
||||
if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings(devmode))
|
||||
{
|
||||
WARN("Failed to update registry\n");
|
||||
ret = DISP_CHANGE_NOTUPDATED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & (CDS_TEST | CDS_NORESET))
|
||||
ret = DISP_CHANGE_SUCCESSFUL;
|
||||
else
|
||||
{
|
||||
if (macdrv_set_display_mode(&displays[0], display_mode))
|
||||
{
|
||||
SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp,
|
||||
MAKELPARAM(width, height));
|
||||
ret = DISP_CHANGE_SUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Failed to set display mode\n");
|
||||
ret = DISP_CHANGE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
CFRelease(display_modes);
|
||||
macdrv_free_displays(displays);
|
||||
|
||||
if (i >= count)
|
||||
{
|
||||
/* no valid modes found */
|
||||
ERR("No matching mode found %ux%ux%d @%u!\n", devmode->dmPelsWidth, devmode->dmPelsHeight,
|
||||
bpp, devmode->dmDisplayFrequency);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EnumDisplayMonitors (MACDRV.@)
|
||||
*/
|
||||
|
@ -426,8 +660,11 @@ void macdrv_displays_changed(const macdrv_event *event)
|
|||
|
||||
/* A system display change will get delivered to all GUI-attached threads,
|
||||
so the desktop-window-owning thread will get it and all others should
|
||||
ignore it. */
|
||||
if (GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId())
|
||||
ignore it. A synthesized display change event due to activation
|
||||
will only get delivered to the activated process. So, it needs to
|
||||
process it (by sending it to the desktop window). */
|
||||
if (event->displays_changed.activating ||
|
||||
GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId())
|
||||
{
|
||||
CGDirectDisplayID mainDisplay = CGMainDisplayID();
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay);
|
||||
|
|
|
@ -121,6 +121,8 @@
|
|||
/* display */
|
||||
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;
|
||||
extern int macdrv_set_display_mode(const struct macdrv_display* display,
|
||||
CGDisplayModeRef display_mode) DECLSPEC_HIDDEN;
|
||||
|
||||
|
||||
/* event */
|
||||
|
@ -149,6 +151,9 @@
|
|||
int type;
|
||||
macdrv_window window;
|
||||
union {
|
||||
struct {
|
||||
int activating;
|
||||
} displays_changed;
|
||||
struct {
|
||||
CGKeyCode keycode;
|
||||
CGEventFlags modifiers;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
@ cdecl ActivateKeyboardLayout(long long) macdrv_ActivateKeyboardLayout
|
||||
@ cdecl Beep() macdrv_Beep
|
||||
@ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) macdrv_ChangeDisplaySettingsEx
|
||||
@ cdecl CreateDesktopWindow(long) macdrv_CreateDesktopWindow
|
||||
@ cdecl CreateWindow(long) macdrv_CreateWindow
|
||||
@ cdecl DestroyWindow(long) macdrv_DestroyWindow
|
||||
|
|
Loading…
Reference in New Issue