I want to know which metrics are used to calculate the correct line height (vertical distance between the baselines of 2 adjacent lines of text). "Correct" shall arbitrarily defined as "whatever DrawTextW does".
The accepted answer here appears to follow what the graph provided in this MSDN article says:
TEXTMETRICW.tmHeight + TEXTMETRICW.tmExternalLeading;
But that does not appear to be correct. Some testing with 2 pieces of text, each of which consists of 2 lines:
// RECT rc is more than large enough to fit any text
int HeightChinese = DrawTextW(hdc, L"中\r\n文", -1, &rc, 0);
int HeightLatin = DrawTextW(hdc, L"Latin,\r\nlatin!", -1, &rc, 0);
The expected return values should be 2 * <SomethingUnknown>.
One observation is that the return value of DrawTextW will always match the RECT output if DT_CALCRECT were used, for all fonts that I have on my machine. So I will assume that using DT_CALCRECT does not provide any additional value over using the return value of DrawTextW.
For all fonts on my machine, these are true:
HeightChinese == HeightLatin
LOGFONTW.lfHeight == TEXTMETRICW.tmHeight (1).
For most fonts on my machine, this is true:
HeightXxx == 2 * TEXTMETRICW.tmHeight
Which already contradicts the formula provided in the other question (TEXTMETRICW.tmExternalLeading does not play a role).
For example, "Arial" with LOGFONTW.lfHeight = 36 will have TEXTMETRICW.tmExternalLeading = 1, and HeightXxx == 72 (not 74). The distance between the lines when taking a screenshot and measuing the pixels is also 72 (so it appears that the return value can be trusted).
At the same time, "Segoe UI" with LOGFONTW.lHeight = 43 will have TEXTMETRICW.tmExternalLeading = 0, and HeightXxx == 84 (not 86).
This is a list of all anomalous fonts on my system:
"FontName" -- "DrawText return value" vs "2 * TEXTMETRICW.tmHeight"
Ebrima -- 84 vs 86
Leelawadee UI -- 84 vs 86
Leelawadee UI Semilight -- 84 vs 86
Lucida Sans Unicode -- 96 vs 98
Malgun Gothic -- 84 vs 86
Malgun Gothic Semilight -- 84 vs 86
Microsoft Tai Le -- 80 vs 82
Microsoft YaHei -- 82 vs 84
Microsoft YaHei UI Light -- 82 vs 84
MS Gothic -- 66 vs 64
MS UI Gothic -- 66 vs 64
MS PGothic -- 66 vs 64
Nirmala UI -- 84 vs 86
Nirmala UI Semilight -- 84 vs 86
Palatino Linotype -- 84 vs 86
Segoe UI -- 84 vs 86
Segoe UI Black -- 84 vs 86
Segoe UI Historic -- 84 vs 86
Segoe UI Light -- 84 vs 86
Segoe UI Semibold -- 84 vs 86
Segoe UI Semilight -- 84 vs 86
Segoe UI Symbol -- 84 vs 86
SimSun -- 66 vs 64
NSimSun -- 66 vs 64
SimSun-ExtB -- 66 vs 64
Verdana -- 76 vs 78
Webdings -- 62 vs 64
Yu Gothic UI -- 84 vs 86
Yu Gothic UI Semibold -- 84 vs 86
Yu Gothic UI Light -- 84 vs 86
Yu Gothic UI Semilight -- 84 vs 86
MS Mincho -- 66 vs 64
MS PMincho -- 66 vs 64
Ubuntu Mono -- 62 vs 64
Sometimes the return value is 2 bigger, sometimes it is 2 smaller than the calculated value.
I have looked at the other values in TEXTMETRICW, and I've also looked at the extra data available int OUTLINETEXTMETRICW, but I could not find any pattern that would explain the observations.
So then, what are the correct metrics to calculate line height? I understand that I could call DrawTextW with DT_CALCRECT to get this value, but I want to understand where this information comes from (and thus, how a font designer could control it in a predictable way).
Here is a gist with a complete Windows application that demonstrates this. All the interesting stuff is in WM_PAINT. Search for #EDIT for some interesting code switches and breakpoints. At the time of posting this question, my GitHub account has been flagged, and the Gist is temporarily unavailable. I hope this can be resolved quickly.
(1) I am using EnumFontFamiliesEx to enumerate all fonts, and it happens to provide LOGFONTW structs with positive lfHeight values. That means I am using cell height rather than character height. While character height is the more typical way of specifying font height, that is sort of irrelevant here, it just so happens that cell height is equal to TEXTMETRICW.tmHeight, but character height isn't. The relevant value for calculations is TEXTMETRICW.tmHeight, and not LOGFONTW.lfHeight.
As Jonathan Potter pointed out, the formula TEXTMETRICW.tmHeight should have been correct, and if the DT_EXTERNALLEADING flag is set, then it's TEXTMETRICW.tmHeight + TEXTMETRICW.tmExternalLeading.
I reverse-engineered DrawTextExW with Ghidra and the reason the numbers were sometimes off is not DrawTextExW itself. DrawTextExW internally uses a DT_InitDrawTextInfo, which in turn uses GetTextMetricsW and calculates the line height according to the above formula.
However, consider this code to probe all fonts:
LOGFONTW Probe = {};
Probe.lfCharSet = DEFAULT_CHARSET;
EnumFontFamiliesExW(hdc, &Probe, InitializeFontInfo_EnumFontFamiliesCallback, NULL, 0);
static int CALLBACK InitializeFontInfo_EnumFontFamiliesCallback(const LOGFONTW *LogFont, const TEXTMETRICW *TextMetric, DWORD FontType, LPARAM lParam)
{
FONT_INFO tmp = {};
tmp.LogFont = *LogFont;
tmp.TextMetric = *TextMetric;
FontInfo.push_back(tmp);
return 1;
}
Here, for the Segoe UI font, for example, LogFont->lfHeight will be 43.
And so, TextMetric->tmHeight will also be 43, which, you would think, makes sense to some degree.
However:
If you go ahead and select this LogFont into a HDC, and then use GetTextMetricsW, like so:
HFONT Font = CreateFontIndirectW(LogFont);
SelectObject(hdc, Font);
TEXTMETRICW TextMetric = {};
GetTextMetricsW(hdc, &TextMetric);
Then TextMetric->tmHeight == 42 even though LogFont->lfHeight == 43.
In other words, the values provided to the EnumFontFamiliesExW callback for its TEXTMETRICW parameter cannot be trusted. Although you could argue that the bug is elsewhere, and selecting a LogFont->lfHeight == 43 font should really also produce a TextMetric->tmHeight == 43 text metric, but I suppose that's too much to ask. My guess is that there's a floating point conversion going on somewhere in there, and that occasionally produces a rounding error for some numbers.
DrawText() only uses TEXTMETRIC.tmExternalLeading if the DT_EXTERNALLEADING flag is set when you call it - you don't seem to have taken that into account.
The line height formula is basically:
int iLineHeight = tm.tmHeight + ((format & DT_EXTERNALLEADING) ? tm.tmExternalLeading : 0);
Related
I'm trying to programmatically add an NSDrawer to my app's main window (which also has an NSOutlineViewwhich was setup in IB):
Ivar:
var dd: NSDrawer? = nil
Then, when a disclosure triangle button is clicked:
if dd == nil {
var drawer_rect = NSInsetRect(self.window.frame, 30, 30).size
drawer_rect.height = 150
dd = NSDrawer.init(contentSize: drawer_rect, preferredEdge: NSRectEdge.minY)
dd!.contentView = self.status_scroll
dd!.parentWindow = self.window
}
So when the user tries to 'disclose' the drawer, the above code creates an NSDrawer and then displays it. It all works fine but Xcode dumps the following out as the parentWindow is set:
[General] ERROR: Setting <NSOutlineView: 0x100f0b9b0> as the first responder for window <NSDrawerWindow: 0x100fc8900>, but it is in a different window (<NSWindow: 0x6080001e0600>)! This would eventually crash when the view is freed. The first responder will be set to nil.
(
0 AppKit 0x00007fff9fc289cf -[NSWindow _validateFirstResponder:] + 557
1 AppKit 0x00007fff9f3a374c -[NSWindow _setFirstResponder:] + 31
2 AppKit 0x00007fff9f90c35b -[NSDrawerWindow _setParentWindow:] + 64
3 AppKit 0x00007fff9f90b666 -[NSDrawer(DrawerInternals) _doSetParentWindow:] + 382
4 AppKit 0x00007fff9f907786 -[NSDrawer setParentWindow:] + 78
Comment out the setting of the parentWindow and nothing gets dumped to the console.
NSDrawer is deprecated as per Apple documentation. You should consider a different design. If you still use NSDrawer, you may face such issues.
I am poking around in the file properties for images, specifically jpg files created by a camera/scanner/adobe/etc.
There is one detail that is different than the rest. The image dimensions seems to have a Unicode codepoint that doesn't appear in the displayed text. The text appears as something like: 3264 x 2448.
As it turns out, there are codepoints on either end of this string that I cannot figure out. It is probably very straight forward, but after my searching I am at a loss.
The property documentation can be found here:
System.Image.Dimensions
property format: {6444048F-4C8B-11D1-8B70-080036B11A03}
0xd => 13 => property id (for Systems.Image.Dimensions)
3264 x 2448 => Image dimensions as the "appear" on the screen
Here is what I have (Python 3.5 output):
0xd => 3264 x 2448 0xd => b"?3264 x 2448?" len: 13
This is the actual string converted to hex bytes.
Hex Bytes: e2 80 aa 33 32 36 34 20 78 20 32 34 34 38 e2 80 ac
Character: ?? ?? ?? 3 2 6 4 x 2 4 4 8 ?? ?? ??
Does anyone know what the "0xe280aa" and "0xe280ac" are and what I am missing?
They are the only "interesting" characters in the entire properties collection for a jpg image. I don't know what they are, or why they are present.
Your property text is encoded in UTF-8.
e2 80 aa is the UTF-8 encoding of Unicode codepoint U+202A LEFT-TO-RIGHT EMBEDDING.
e2 80 ac is the UTF-8 encoding of Unicode codepoint U+202C POP DIRECTIONAL FORMATTING.
These markers are used when embedding left-to-right text in bidirectional text.
Raymond Chen blogged about this in relation to a similar issue with filenames displayed in Windows Explorer:
Why is there an invisible U+202A at the start of my file name?
Is there any way to detect whether a console app is running with Windows 10's new features enabled?
This MSDN page shows that HKEY_CURRENT_USER\Console\ForceV2, HKEY_CURRENT_USER\Console\LineWrap and HKEY_CURRENT_USER\Console\{name}\LineWrap control it, but besides that being less robust to parse, it may not be correct. If the user switches to or from legacy mode, the change won't take effect until the console relaunches.
If I develop the app, I can do the check at startup. There could have been a race condition though, which renders the registry check useless for any practical use. I am curious what the solution would be for third party console windows.
There seems to be no API for that, though I'd expect one to surface in some later SDK (maybe additional hyper-extended flags in GetConsoleMode).
Meanwhile, the following is a quick hack which attempts to detect the resize-wider capability of the new console, based on checking the ptMaxTrackSize.X value returned by GetMinMaxInfo.
The legacy console doesn't allow resizing the window wider than the screen buffer width, while the new one does. On the assumptions that (a) the console is running at full buffer width i.e. has no horizontal scrollbar, and (b) it's not already stretched to the full/max screen width, it's fairly straightforward to check whether the window allows itself to be resized wider (new console) or not (legacy console). Should be noted that assumption (a) could technically be avoided by manually converting the buffer width from characters to pixels, rather than relying on GetWindowRect, but assumption (b) is pretty much unavoidable.
This is the code (disclaimer: quick-and-dirty proof-of concept, no error checking etc).
int main()
{
// largest possible console size for given font and desktop
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD cd = GetLargestConsoleWindowSize(hOut);
SHORT nScrMaxXch = cd.X,
nScrMaxYch = cd.Y;
// current and max console sizes for given screen buffer
CONSOLE_SCREEN_BUFFER_INFOEX csbix = { sizeof(csbix) };
GetConsoleScreenBufferInfoEx(hOut, &csbix);
SHORT nWndXch = csbix.srWindow.Right - csbix.srWindow.Left + 1,
nWndYch = csbix.srWindow.Bottom - csbix.srWindow.Top + 1;
SHORT nWndMaxXch = csbix.dwMaximumWindowSize.X,
nWndMaxYch = csbix.dwMaximumWindowSize.Y;
wprintf(L"chars: wnd-size %d %d, max-wnd-size %d %d, largest-size %d %d\n",
nWndXch, nWndYch, nWndMaxXch, nWndMaxYch, nScrMaxXch, nScrMaxYch);
// current window size
HWND hWnd = GetConsoleWindow();
RECT rc; GetWindowRect(hWnd, &rc);
LONG nWndXpx = rc.right - rc.left,
nWndYpx = rc.bottom - rc.top;
// max window tracking size
MINMAXINFO mmi = { 0 };
SendMessage(hWnd, WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
LONG nWndMaxXpx = mmi.ptMaxTrackSize.x,
nWndMaxYpx = mmi.ptMaxTrackSize.y;
wprintf(L"pixels: wnd-size %lu %lu, max-tracking-size %lu %lu\n",
nWndXpx, nWndYpx, nWndMaxXpx, nWndMaxYpx);
if (nWndXch == nWndMaxXch // full buffer width, no h-scrollbar
&& nWndXch < nScrMaxXch // not already stretched to full screen width
&& nWndMaxXpx > nWndXpx) // allowed to resized wider
wprintf(L"\n...most likely a Win10 console with ForceV2 enabled\n");
return 0;
}
This is the output when run in a legacy console.
chars: wnd-size 80 25, max-wnd-size 80 71, largest-size 240 71
pixels: wnd-size 677 443, max-tracking-size 677 1179
This is the output when run in the new console.
chars: wnd-size 80 25, max-wnd-size 80 71, largest-size 239 71
pixels: wnd-size 677 443, max-tracking-size 1936 1186
...most likely a Win10 console with ForceV2 enabled
I'm working on a project in order to exchange large data from PC to Android device throught NFC. I'm using ACR122.
The following is a general exemple of data sent :
// ADPU
FF FF 00 00 00 nn // CLA, INS, P1, P2, Le, Lc
D4 40 // TFI, PD0
01 // (Mi), Target
// LLCP
13 20 // DSAP, PTYPE, SSAP
00 // Sequence
D4 40 // TFI, PD0
// SNEP
10 02 // Protocol Version, Action
nn nn nn nn // Total SNEP Length
// NDEF Header
A2 // First byte (MB = 1, ME = 0, Cf = 1, SR = 0, Il, TNF)
22 // Type length
mm mm mm mm // Payload length
// NDEF Content
61.....65 // Type (34 bytes in that case)
01.....01 // Payload (mm mm mm mm bytes)
Here, I send a Record (not short record).So the NDEF header allows to enter a 4 bytes payload length.
Finaly, my question is how could we send a such large payload regarding the 1 byte APDU Lc ?
If this limitation is only due to the pn532 chip or PS/SC, what alternative hardware would you suggest ?
Thank you for any clarification
EDIT :
I found what I was looking for here :
Sending Extended APDU to Javacard
It's a hardware problem, PN532 don't support Extended APDU.
As you've already found out the ACR122 does not support extended APDU due to a limitation of the PN532 chip.
However, there is no need to pack the entire SNEP transfer into a single APDU. You can split the payload into multiple smaller frames and send them one after another. It's only important that the NDEF header gets transmitted as a whole in the first frame.
I'm searching for a solution in my firefox addon to detect when the user workspace has locked/released. In google chrome there is an easy API chrome.idle.onStateChanged.addListener for it, is there something similar in firefox or any possibility to do that, platform independent?
By the way, I use the addon sdk.
I've already tried the idle service:
Cc["#mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService)
but I just gives me access to some idle timeout or system when go to sleep and not to just workspace locked.
Edit: With "workspace locked" I mean the user lock the workspace with ctrl + alt + delete. I don't know how this exactly work on OSX or linux.
Edit2: I working in Windows 8.1 currently, but I guess the chrome.idle handler works cross platform.
Edit3: What i currently get out of current answers is
1. That there not exist a cross-platform solution, neither in chrome nor in firefox.
chrome.idle.onStateChanged seems to work different on windows, linux and osx. Only windows can handle that "locked" behaviour as expected. I can't test OSX, on ubuntu 14 it doesn't work for me.
2. For firefox there some in-depth code things to try to make it working - see answer bellow from Noitidart in this topic.
Edit4: Noitidart have found a solution for windows - github link.
I don't know how to detect screen lock but there are these observer notifications:
https://developer.mozilla.org/en-US/docs/Observer_Notifications#Idle_Service
Also the computer sleep wake notifications. ill ask around for lock screen thats an interesting one.
Some useful chat about the subject, looking at how google chrome does it:
[12:33] ok guys question about actual work. anyone know how to detect if screen was locked? apparently google chrome has a method: https://developer.chrome.com/extensions/idle#event-onStateChanged
[12:45] anyone know of a MXR or DXR for google chromes codebase?
[12:46] mxr.mozilla.org/chromium
[12:52] Ms2ger: can you help me find how they test screen lock. im looking here: http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_api_unittest.cc#84
[12:56] oh yuck it looks like they poll: http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_manager.h#118
maybe they arent polling.
check this out:
http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_manager.cc#246
244 void IdleManager::UpdateIdleStateCallback(int idle_time) {
245 DCHECK(thread_checker_.CalledOnValidThread());
246 bool locked = idle_time_provider_->CheckIdleStateIsLocked();
247 int listener_count = 0;
leads to: http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#52
52 bool CheckIdleStateIsLocked() {
53 return ui::IsWorkstationLocked() || IsScreensaverRunning();
54 }
so this leads us to test if screensaver running or workstation locked
leads to:
http://mxr.mozilla.org/chromium/search?string=IsWorkstationLocked
we see just one implementation (its curious because there is no linux support but it doesnt say so on the chrome docs page, so maybe i couldnt find it)
Windows
http://mxr.mozilla.org/chromium/source/src/ui/base/win/lock_state.cc#11
11 bool IsWorkstationLocked() {
12 bool is_locked = true;
13 HDESK input_desk = ::OpenInputDesktop(0, 0, GENERIC_READ);
14 if (input_desk) {
15 wchar_t name[256] = {0};
16 DWORD needed = 0;
17 if (::GetUserObjectInformation(
18 input_desk, UOI_NAME, name, sizeof(name), &needed)) {
19 is_locked = lstrcmpi(name, L"default") != 0;
20 }
21 ::CloseDesktop(input_desk);
22 }
23 return is_locked;
24 }
Mac
see the screensaver section below, the screenlock is handled via there as well
http://mxr.mozilla.org/chromium/search?string=IsScreensaverRunning&find=&findi=&filter=^%5B^\0%5D*%24&hitlimit=&tree=chromium
we see in this search results 2 implementations, mac and windows it looks like no support for linux, which is curious because the chrome.idle page doesnt mention this on docs, maybe i just couldnt find it
windows implementation: http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#39
39 bool IsScreensaverRunning() {
40 DWORD result = 0;
41 if (::SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &result, 0))
42 return result != FALSE;
43 return false;
44 }
45
mac implementation: http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_mac.mm#28
28 - (id)init {
29 if ((self = [super init])) {
30 NSDistributedNotificationCenter* distCenter =
31 [NSDistributedNotificationCenter defaultCenter];
32 [distCenter addObserver:self
33 selector:#selector(onScreenSaverStarted:)
34 name:#"com.apple.screensaver.didstart"
35 object:nil];
36 [distCenter addObserver:self
37 selector:#selector(onScreenSaverStopped:)
38 name:#"com.apple.screensaver.didstop"
39 object:nil];
40 [distCenter addObserver:self
41 selector:#selector(onScreenLocked:)
42 name:#"com.apple.screenIsLocked"
43 object:nil];
44 [distCenter addObserver:self
45 selector:#selector(onScreenUnlocked:)
46 name:#"com.apple.screenIsUnlocked"
47 object:nil];
48 }
49 return self;
50 }
so to sum this all up:
[13:32] for windows its peice of cake winapi has call to test if screen is locked or scrensaver running
[13:32] for mac they dont have screen lock test. they just have screensaver test, but its an observer method
[13:32] for linux they dont have screen lock nor screen saver test. real odd. ill ask the guy if he knows which os's they support chrome.idle in
edit: actually i found the linux implementation. back from the search results of: CheckIdleStateLocked: http://mxr.mozilla.org/chromium/search?string=CheckIdleStateIsLocked
http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_linux.cc#24
24 bool CheckIdleStateIsLocked() {
25 // Usually the screensaver is used to lock the screen, so we do not need to
26 // check if the workstation is locked.
27 #if defined(OS_CHROMEOS)
28 return false;
29 #elif defined(USE_OZONE)
30 return false;
31 #else
32 return ScreensaverWindowFinder::ScreensaverWindowExists();
33 #endif
34 }
Leads to ask how is ScreensaverWindowExists we find this: http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc
15 bool ScreensaverWindowFinder::ScreensaverWindowExists() {
16 gfx::X11ErrorTracker err_tracker;
17 ScreensaverWindowFinder finder;
18 ui::EnumerateTopLevelWindows(&finder);
19 return finder.exists_ && !err_tracker.FoundNewError();
20 }
Leads to what is EnumerateTopLevelWindows http://mxr.mozilla.org/chromium/source/src/ui/base/x/x11_util.cc#1059:
1059 void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
1060 std::vector<XID> stack;
1061 if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
1062 // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
1063 // to old school enumeration of all X windows. Some WMs parent 'top-level'
1064 // windows in unnamed actual top-level windows (ion WM), so extend the
1065 // search depth to all children of top-level windows.
1066 const int kMaxSearchDepth = 1;
1067 ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
1068 return;
1069 }
1070 XMenuList::GetInstance()->InsertMenuWindowXIDs(&stack);
1071
1072 std::vector<XID>::iterator iter;
1073 for (iter = stack.begin(); iter != stack.end(); iter++) {
1074 if (delegate->ShouldStopIterating(*iter))
1075 return;
1076 }
1077 }
1078
We say they call delegate->ShouldStopIterating which was seen in same file as ScreensaverWindowExists: http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc
22 bool ScreensaverWindowFinder::ShouldStopIterating(XID window) {
23 if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
24 return false;
25 exists_ = true;
26 return true;
27 }
Leads to ask what is IsWindowVisible and IsScreensaverWindow
*IsScreensaverWindow, in same file of ScreensaverWindowExists: http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc
29 bool ScreensaverWindowFinder::IsScreensaverWindow(XID window) const {
30 // It should occupy the full screen.
31 if (!ui::IsX11WindowFullScreen(window))
32 return false;
33
34 // For xscreensaver, the window should have _SCREENSAVER_VERSION property.
35 if (ui::PropertyExists(window, "_SCREENSAVER_VERSION"))
36 return true;
37
38 // For all others, like gnome-screensaver, the window's WM_CLASS property
39 // should contain "screensaver".
40 std::string value;
41 if (!ui::GetStringProperty(window, "WM_CLASS", &value))
42 return false;
43
44 return value.find("screensaver") != std::string::npos;
45 }
IsWindowVisible: http://mxr.mozilla.org/chromium/source/src/ui/base/x/x11_util.cc#546
546 bool IsWindowVisible(XID window) {
547 TRACE_EVENT0("ui", "IsWindowVisible");
548
549 XWindowAttributes win_attributes;
550 if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes))
551 return false;
552 if (win_attributes.map_state != IsViewable)
553 return false;
554
555 // Minimized windows are not visible.
556 std::vector<XAtom> wm_states;
557 if (GetAtomArrayProperty(window, "_NET_WM_STATE", &wm_states)) {
558 XAtom hidden_atom = GetAtom("_NET_WM_STATE_HIDDEN");
559 if (std::find(wm_states.begin(), wm_states.end(), hidden_atom) !=
560 wm_states.end()) {
561 return false;
562 }
563 }