Skip to content
This repository was archived by the owner on May 8, 2018. It is now read-only.

Commit b93094c

Browse files
author
Eun
committed
+ Move windows of disabled monitor
1 parent 172f670 commit b93094c

File tree

7 files changed

+105
-218
lines changed

7 files changed

+105
-218
lines changed

DisableMonitor-Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
<key>CFBundlePackageType</key>
1818
<string>APPL</string>
1919
<key>CFBundleShortVersionString</key>
20-
<string>1.1</string>
20+
<string>1.2</string>
2121
<key>CFBundleSignature</key>
2222
<string>????</string>
2323
<key>CFBundleVersion</key>
24-
<string>1.1</string>
24+
<string>1.2</string>
2525
<key>LSMinimumSystemVersion</key>
2626
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
2727
<key>LSUIElement</key>

DisableMonitor.xcodeproj/project.pbxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
592CED8018FEBDB300FDDF65 /* GLFW.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLFW.m; sourceTree = "<group>"; };
3333
592CED8618FEC42800FDDF65 /* status_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = status_icon.png; sourceTree = "<group>"; };
3434
598E9891193DC99B005DEB10 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
35-
598E9893193DC9DD005DEB10 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
3635
59B5766618FFDC6700B57E77 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = "<group>"; };
3736
8D1107310486CEB800E47090 /* DisableMonitor-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DisableMonitor-Info.plist"; sourceTree = "<group>"; };
3837
8D1107320486CEB800E47090 /* DisableMonitor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DisableMonitor.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -208,7 +207,6 @@
208207
isa = PBXVariantGroup;
209208
children = (
210209
089C165DFE840E0CC02AAC07 /* English */,
211-
598E9893193DC9DD005DEB10 /* de */,
212210
);
213211
name = Localizable.strings;
214212
sourceTree = "<group>";
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<VariablesViewState
3+
version = "1.0">
4+
<ContextStates>
5+
<ContextState
6+
contextName = "-[DisableMonitorAppDelegate MoveAllWindows:to:]:DisableMonitorAppDelegate.m">
7+
<PersistentStrings>
8+
<PersistentString
9+
value = "[app processIdentifier]">
10+
</PersistentString>
11+
</PersistentStrings>
12+
</ContextState>
13+
</ContextStates>
14+
</VariablesViewState>

DisableMonitor.xcodeproj/xcuserdata/salzmann.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

Lines changed: 0 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -2,214 +2,4 @@
22
<Bucket
33
type = "1"
44
version = "2.0">
5-
<Breakpoints>
6-
<BreakpointProxy
7-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
8-
<BreakpointContent
9-
shouldBeEnabled = "No"
10-
ignoreCount = "0"
11-
continueAfterRunningActions = "No"
12-
filePath = "DisableMonitorAppDelegate.m"
13-
timestampString = "423479947.018587"
14-
startingColumnNumber = "9223372036854775807"
15-
endingColumnNumber = "9223372036854775807"
16-
startingLineNumber = "257"
17-
endingLineNumber = "257"
18-
landmarkName = "-DetectMonitors:"
19-
landmarkType = "5">
20-
</BreakpointContent>
21-
</BreakpointProxy>
22-
<BreakpointProxy
23-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
24-
<BreakpointContent
25-
shouldBeEnabled = "No"
26-
ignoreCount = "0"
27-
continueAfterRunningActions = "No"
28-
filePath = "DisableMonitorAppDelegate.m"
29-
timestampString = "423479947.018587"
30-
startingColumnNumber = "9223372036854775807"
31-
endingColumnNumber = "9223372036854775807"
32-
startingLineNumber = "304"
33-
endingLineNumber = "304"
34-
landmarkName = "-menuNeedsUpdate:"
35-
landmarkType = "5">
36-
</BreakpointContent>
37-
</BreakpointProxy>
38-
<BreakpointProxy
39-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
40-
<BreakpointContent
41-
shouldBeEnabled = "No"
42-
ignoreCount = "0"
43-
continueAfterRunningActions = "No"
44-
filePath = "DisableMonitorAppDelegate.m"
45-
timestampString = "423479947.018587"
46-
startingColumnNumber = "9223372036854775807"
47-
endingColumnNumber = "9223372036854775807"
48-
startingLineNumber = "235"
49-
endingLineNumber = "235"
50-
landmarkName = "-MonitorResolution:"
51-
landmarkType = "5">
52-
</BreakpointContent>
53-
</BreakpointProxy>
54-
<BreakpointProxy
55-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
56-
<BreakpointContent
57-
shouldBeEnabled = "No"
58-
ignoreCount = "0"
59-
continueAfterRunningActions = "No"
60-
filePath = "DisableMonitorAppDelegate.m"
61-
timestampString = "423479947.018587"
62-
startingColumnNumber = "9223372036854775807"
63-
endingColumnNumber = "9223372036854775807"
64-
startingLineNumber = "297"
65-
endingLineNumber = "297"
66-
landmarkName = "-menuNeedsUpdate:"
67-
landmarkType = "5">
68-
</BreakpointContent>
69-
</BreakpointProxy>
70-
<BreakpointProxy
71-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
72-
<BreakpointContent
73-
shouldBeEnabled = "No"
74-
ignoreCount = "0"
75-
continueAfterRunningActions = "No"
76-
filePath = "DisableMonitorAppDelegate.m"
77-
timestampString = "423479947.018587"
78-
startingColumnNumber = "9223372036854775807"
79-
endingColumnNumber = "9223372036854775807"
80-
startingLineNumber = "300"
81-
endingLineNumber = "300"
82-
landmarkName = "-menuNeedsUpdate:"
83-
landmarkType = "5">
84-
</BreakpointContent>
85-
</BreakpointProxy>
86-
<BreakpointProxy
87-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
88-
<BreakpointContent
89-
shouldBeEnabled = "No"
90-
ignoreCount = "0"
91-
continueAfterRunningActions = "No"
92-
filePath = "DisableMonitorAppDelegate.m"
93-
timestampString = "423479947.018587"
94-
startingColumnNumber = "9223372036854775807"
95-
endingColumnNumber = "9223372036854775807"
96-
startingLineNumber = "298"
97-
endingLineNumber = "298"
98-
landmarkName = "-menuNeedsUpdate:"
99-
landmarkType = "5">
100-
</BreakpointContent>
101-
</BreakpointProxy>
102-
<BreakpointProxy
103-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
104-
<BreakpointContent
105-
shouldBeEnabled = "No"
106-
ignoreCount = "0"
107-
continueAfterRunningActions = "No"
108-
filePath = "DisableMonitorAppDelegate.m"
109-
timestampString = "423479947.018587"
110-
startingColumnNumber = "9223372036854775807"
111-
endingColumnNumber = "9223372036854775807"
112-
startingLineNumber = "323"
113-
endingLineNumber = "323"
114-
landmarkName = "-menuNeedsUpdate:"
115-
landmarkType = "5">
116-
</BreakpointContent>
117-
</BreakpointProxy>
118-
<BreakpointProxy
119-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
120-
<BreakpointContent
121-
shouldBeEnabled = "No"
122-
ignoreCount = "0"
123-
continueAfterRunningActions = "No"
124-
filePath = "DisableMonitorAppDelegate.m"
125-
timestampString = "423479947.018587"
126-
startingColumnNumber = "9223372036854775807"
127-
endingColumnNumber = "9223372036854775807"
128-
startingLineNumber = "377"
129-
endingLineNumber = "377"
130-
landmarkName = "-menuNeedsUpdate:"
131-
landmarkType = "5">
132-
</BreakpointContent>
133-
</BreakpointProxy>
134-
<BreakpointProxy
135-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
136-
<BreakpointContent
137-
shouldBeEnabled = "No"
138-
ignoreCount = "0"
139-
continueAfterRunningActions = "No"
140-
filePath = "DisableMonitorAppDelegate.m"
141-
timestampString = "423479947.018587"
142-
startingColumnNumber = "9223372036854775807"
143-
endingColumnNumber = "9223372036854775807"
144-
startingLineNumber = "394"
145-
endingLineNumber = "394"
146-
landmarkName = "-menuNeedsUpdate:"
147-
landmarkType = "5">
148-
</BreakpointContent>
149-
</BreakpointProxy>
150-
<BreakpointProxy
151-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
152-
<BreakpointContent
153-
shouldBeEnabled = "No"
154-
ignoreCount = "0"
155-
continueAfterRunningActions = "No"
156-
filePath = "DisableMonitorAppDelegate.m"
157-
timestampString = "423479947.018587"
158-
startingColumnNumber = "9223372036854775807"
159-
endingColumnNumber = "9223372036854775807"
160-
startingLineNumber = "388"
161-
endingLineNumber = "388"
162-
landmarkName = "-menuNeedsUpdate:"
163-
landmarkType = "5">
164-
</BreakpointContent>
165-
</BreakpointProxy>
166-
<BreakpointProxy
167-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
168-
<BreakpointContent
169-
shouldBeEnabled = "No"
170-
ignoreCount = "0"
171-
continueAfterRunningActions = "No"
172-
filePath = "DisableMonitorAppDelegate.m"
173-
timestampString = "423479947.018587"
174-
startingColumnNumber = "9223372036854775807"
175-
endingColumnNumber = "9223372036854775807"
176-
startingLineNumber = "389"
177-
endingLineNumber = "389"
178-
landmarkName = "-menuNeedsUpdate:"
179-
landmarkType = "5">
180-
</BreakpointContent>
181-
</BreakpointProxy>
182-
<BreakpointProxy
183-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
184-
<BreakpointContent
185-
shouldBeEnabled = "No"
186-
ignoreCount = "0"
187-
continueAfterRunningActions = "No"
188-
filePath = "DisableMonitorAppDelegate.m"
189-
timestampString = "423479947.018587"
190-
startingColumnNumber = "9223372036854775807"
191-
endingColumnNumber = "9223372036854775807"
192-
startingLineNumber = "85"
193-
endingLineNumber = "85"
194-
landmarkName = "-ToggleMonitor:enabled:"
195-
landmarkType = "5">
196-
</BreakpointContent>
197-
</BreakpointProxy>
198-
<BreakpointProxy
199-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
200-
<BreakpointContent
201-
shouldBeEnabled = "No"
202-
ignoreCount = "0"
203-
continueAfterRunningActions = "No"
204-
filePath = "DisableMonitorAppDelegate.m"
205-
timestampString = "423479947.018587"
206-
startingColumnNumber = "9223372036854775807"
207-
endingColumnNumber = "9223372036854775807"
208-
startingLineNumber = "49"
209-
endingLineNumber = "49"
210-
landmarkName = "screenNameForDisplay()"
211-
landmarkType = "7">
212-
</BreakpointContent>
213-
</BreakpointProxy>
214-
</Breakpoints>
2155
</Bucket>

DisableMonitorAppDelegate.m

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ @implementation DisableMonitorAppDelegate
2323

2424
@synthesize window;
2525

26-
26+
extern AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out);
2727
extern io_service_t IOServicePortFromCGDisplayID(CGDirectDisplayID displayID);
2828
extern CGError CGSConfigureDisplayEnabled(CGDisplayConfigRef, CGDirectDisplayID, bool);
2929
extern CGDisplayErr CGSGetDisplayList(CGDisplayCount maxDisplays, CGDirectDisplayID * onlineDspys, CGDisplayCount * dspyCnt);
@@ -36,9 +36,6 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
3636
}
3737

3838

39-
40-
static void KeyArrayCallback(const void* key, const void* value, void* context) { CFArrayAppendValue(context, key); }
41-
4239
NSString* screenNameForDisplay(CGDirectDisplayID displayID)
4340
{
4441
NSString *screenName = nil;
@@ -77,11 +74,94 @@ -(void)ShowError:(NSString*)error
7774

7875
#define ShowError(...) [self ShowError:[NSString stringWithFormat:__VA_ARGS__]];
7976

77+
-(void)MoveAllWindows:(CGDirectDisplayID) display to:(CGDirectDisplayID*)todisplay
78+
{
79+
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID);
80+
CGRect bounds = CGDisplayBounds(display);
81+
CGRect dstbounds = CGDisplayBounds(todisplay);
82+
for (NSDictionary *windowItem in ((NSArray *)windowList))
83+
{
84+
NSNumber *windowLayer = (NSNumber*)[windowItem objectForKey:(id)kCGWindowLayer];
85+
if ([windowLayer intValue] == 0)
86+
{
87+
CGRect windowBounds;
88+
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[windowItem objectForKey:(id)kCGWindowBounds], &windowBounds);
89+
if (CGRectContainsRect(bounds, windowBounds))
90+
{
91+
BOOL bSuccess = false;
92+
NSNumber *windowNumber = (NSNumber*)[windowItem objectForKey:(id)kCGWindowNumber];
93+
NSNumber *windowOwnerPid = (NSNumber*)[windowItem objectForKey:(id)kCGWindowOwnerPID];
94+
AXUIElementRef appRef = AXUIElementCreateApplication([windowOwnerPid longValue]);
95+
if (appRef != nil) {
96+
97+
CFArrayRef _windows;
98+
if (AXUIElementCopyAttributeValues(appRef, kAXWindowsAttribute, 0, 100, &_windows) == kAXErrorSuccess)
99+
{
100+
for (int i = 0, len = CFArrayGetCount(_windows); i < len; i++)
101+
{
102+
AXUIElementRef _windowItem = CFArrayGetValueAtIndex(_windows,i);
103+
CGWindowID windowID;
104+
if (_AXUIElementGetWindow(_windowItem, &windowID) == kAXErrorSuccess)
105+
{
106+
if (windowID == windowNumber.longValue)
107+
{
108+
NSPoint tmpPos;
109+
tmpPos.x = dstbounds.origin.x;
110+
tmpPos.y = dstbounds.origin.y;
111+
CFTypeRef _position = (CFTypeRef)(AXValueCreate(kAXValueCGPointType, (const void *)&tmpPos));
112+
if(AXUIElementSetAttributeValue(_windowItem,kAXPositionAttribute,(CFTypeRef*)_position) == kAXErrorSuccess){
113+
bSuccess = true;
114+
}
115+
}
116+
}
117+
}
118+
}
119+
CFRelease(appRef);
120+
}
121+
122+
if (!bSuccess)
123+
{
124+
NSLog(@"Could not move window %ld of %ld", windowNumber.longValue, windowOwnerPid.longValue);
125+
}
126+
}
127+
}
128+
129+
}
130+
CFRelease(windowList);
131+
}
132+
80133
-(void)ToggleMonitor:(CGDirectDisplayID) display enabled:(Boolean) enabled
81134
{
135+
136+
82137
CGError err;
83138
CGDisplayConfigRef config;
84139
@try {
140+
141+
if (enabled == false)
142+
{
143+
CGDirectDisplayID displays[0x10];
144+
CGDisplayCount nDisplays = 0;
145+
146+
CGDisplayErr err = CGSGetDisplayList(0x10, displays, &nDisplays);
147+
148+
if (err == 0 && nDisplays > 0)
149+
{
150+
for (int i = 0; i < nDisplays; i++)
151+
{
152+
if (displays[i] == display)
153+
continue;
154+
if (!CGDisplayIsOnline(displays[i]))
155+
continue;
156+
if (!CGDisplayIsActive(displays[i]))
157+
continue;
158+
[self MoveAllWindows:display to:displays[i]];
159+
break;
160+
}
161+
}
162+
}
163+
164+
85165
err = CGBeginDisplayConfiguration (&config);
86166
if (err != 0)
87167
{
@@ -100,6 +180,8 @@ -(void)ToggleMonitor:(CGDirectDisplayID) display enabled:(Boolean) enabled
100180
ShowError(@"Error in CGCompleteDisplayConfiguration: %d", err);
101181
return;
102182
}
183+
184+
103185
}
104186
@catch (NSException *exception) {
105187

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Easily disable or enable a monitor on your Mac!
1010

1111
Changelog
1212
=========
13+
1.2:
14+
* Move windows from disabled monitor to an active one
15+
1316
1.1:
1417
* Resolution can now be changed!
1518
* Bugfixes

0 commit comments

Comments
 (0)