std::vector<et::Screen> et::availableScreens() { std::vector<et::Screen> result; EnumDisplayMonitors(nullptr, nullptr, [](HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) -> BOOL { MONITORINFO info = { sizeof(MONITORINFO) }; GetMonitorInfo(hMonitor, &info); recti screenRect(info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top); recti workarea(info.rcWork.left, info.rcWork.top, info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); std::vector<et::Screen>* r = reinterpret_cast<std::vector<et::Screen>*>(dwData); r->emplace_back(screenRect, workarea, 1); return 1; }, reinterpret_cast<LPARAM>(&result)); return result; }
void nsCairoScreen::Init () { #ifdef MOZ_ENABLE_GTK2 mAvailRect = mRect = nsRect(0, 0, gdk_screen_width(), gdk_screen_height()); // We need to account for the taskbar, etc in the available rect. // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771 // XXX It doesn't change that often, but we should probably // listen for changes to _NET_WORKAREA. // XXX do we care about _NET_WM_STRUT_PARTIAL? That will // add much more complexity to the code here (our screen // could have a non-rectangular shape), but should // lead to greater accuracy. #if GTK_CHECK_VERSION(2,2,0) GdkWindow *root_window = gdk_get_default_root_window(); #else GdkWindow *root_window = GDK_ROOT_PARENT(); #endif // GTK_CHECK_VERSION(2,2,0) long *workareas; GdkAtom type_returned; int format_returned; int length_returned; #if GTK_CHECK_VERSION(2,0,0) GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); #else GdkAtom cardinal_atom = (GdkAtom) XA_CARDINAL; #endif gdk_error_trap_push(); // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here. if (!gdk_property_get(root_window, gdk_atom_intern ("_NET_WORKAREA", FALSE), cardinal_atom, 0, G_MAXLONG - 3, FALSE, &type_returned, &format_returned, &length_returned, (guchar **) &workareas)) { // This window manager doesn't support the freedesktop standard. // Nothing we can do about it, so assume full screen size. return; } // Flush the X queue to catch errors now. gdk_flush(); if (!gdk_error_trap_pop() && type_returned == cardinal_atom && length_returned && (length_returned % 4) == 0 && format_returned == 32) { int num_items = length_returned / sizeof(long); for (int i = 0; i < num_items; i += 4) { nsRect workarea(workareas[i], workareas[i + 1], workareas[i + 2], workareas[i + 3]); if (!mRect.Contains(workarea)) { NS_WARNING("Invalid bounds"); continue; } mAvailRect.IntersectRect(mAvailRect, workarea); } } #elif MOZ_ENABLE_XLIB mScreenNum = 0; mRect.x = mAvailRect.x = 0; mRect.y = mAvailRect.y = 0; mRect.width = mAvailRect.width = 1600; mRect.height = mAvailRect.height = 1200; #endif }
void nsScreenGtk :: Init (GdkWindow *aRootWindow) { // We listen for configure events on the root window to pick up // changes to this rect. We could listen for "size_changed" signals // on the default screen to do this, except that doesn't work with // versions of GDK predating the GdkScreen object. See bug 256646. mAvailRect = mRect = nsIntRect(0, 0, gdk_screen_width(), gdk_screen_height()); #ifdef MOZ_X11 // We need to account for the taskbar, etc in the available rect. // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771 // XXX do we care about _NET_WM_STRUT_PARTIAL? That will // add much more complexity to the code here (our screen // could have a non-rectangular shape), but should // lead to greater accuracy. long *workareas; GdkAtom type_returned; int format_returned; int length_returned; #if GTK_CHECK_VERSION(2,0,0) GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); #else GdkAtom cardinal_atom = (GdkAtom) XA_CARDINAL; #endif gdk_error_trap_push(); // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here. if (!gdk_property_get(aRootWindow, gdk_atom_intern ("_NET_WORKAREA", FALSE), cardinal_atom, 0, G_MAXLONG - 3, FALSE, &type_returned, &format_returned, &length_returned, (guchar **) &workareas)) { // This window manager doesn't support the freedesktop standard. // Nothing we can do about it, so assume full screen size. return; } // Flush the X queue to catch errors now. gdk_flush(); if (!gdk_error_trap_pop() && type_returned == cardinal_atom && length_returned && (length_returned % 4) == 0 && format_returned == 32) { int num_items = length_returned / sizeof(long); for (int i = 0; i < num_items; i += 4) { nsIntRect workarea(workareas[i], workareas[i + 1], workareas[i + 2], workareas[i + 3]); if (!mRect.Contains(workarea)) { // Note that we hit this when processing screen size changes, // since we'll get the configure event before the toolbars have // been moved. We'll end up cleaning this up when we get the // change notification to the _NET_WORKAREA property. However, // we still want to listen to both, so we'll handle changes // properly for desktop environments that don't set the // _NET_WORKAREA property. NS_WARNING("Invalid bounds"); continue; } mAvailRect.IntersectRect(mAvailRect, workarea); } } g_free (workareas); #endif }