Add the platform-dependent stuff from renderingengine.cpp

This commit is contained in:
Desour 2023-03-25 01:40:13 +01:00 committed by sfan5
parent 6a2a569233
commit acbc90a000
7 changed files with 209 additions and 0 deletions

View File

@ -132,6 +132,11 @@ namespace irr
/** \param text: New text of the window caption. */
virtual void setWindowCaption(const wchar_t* text) = 0;
//! Sets the window icon.
/** \param img The icon texture.
\return False if no icon was set. */
virtual bool setWindowIcon(const video::IImage *img) = 0;
//! Returns if the window is active.
/** If the window is inactive,
nothing needs to be drawn. So if you don't want to draw anything
@ -307,6 +312,10 @@ namespace irr
used. */
virtual E_DEVICE_TYPE getType() const = 0;
//! Get the display density in dots per inch.
//! Returns 0.0f on failure.
virtual float getDisplayDensity() const = 0;
//! Check if a driver type is supported by the engine.
/** Even if true is returned the driver may not be available
for a configuration requested when creating the device. */

View File

@ -24,6 +24,8 @@
#include "SIrrCreationParameters.h"
#include "SExposedVideoData.h"
#include "IGUISpriteBank.h"
#include "IImageLoader.h"
#include "IFileSystem.h"
#include <X11/XKBlib.h>
#include <X11/Xatom.h>
@ -171,6 +173,8 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
if (param.WindowMaximized)
maximizeWindow();
setupTopLevelXorgWindow();
}
@ -282,6 +286,72 @@ bool CIrrDeviceLinux::switchToFullscreen()
}
void CIrrDeviceLinux::setupTopLevelXorgWindow()
{
#ifdef _IRR_COMPILE_WITH_X11_
if (CreationParams.DriverType == video::EDT_NULL)
return; // no display and window
os::Printer::log("Configuring X11-specific top level window properties", ELL_DEBUG);
// Set application name and class hints. For now name and class are the same.
// Note: SDL uses the executable name here (i.e. "minetest").
XClassHint *classhint = XAllocClassHint();
classhint->res_name = const_cast<char *>("Minetest");
classhint->res_class = const_cast<char *>("Minetest");
XSetClassHint(XDisplay, XWindow, classhint);
XFree(classhint);
// FIXME: In the future WMNormalHints should be set ... e.g see the
// gtk/gdk code (gdk/x11/gdksurface-x11.c) for the setup_top_level
// method. But for now (as it would require some significant changes)
// leave the code as is.
// The following is borrowed from the above gdk source for setting top
// level windows. The source indicates and the Xlib docs suggest that
// this will set the WM_CLIENT_MACHINE and WM_LOCAL_NAME. This will not
// set the WM_CLIENT_MACHINE to a Fully Qualified Domain Name (FQDN) which is
// required by the Extended Window Manager Hints (EWMH) spec when setting
// the _NET_WM_PID (see further down) but running Minetest in an env
// where the window manager is on another machine from Minetest (therefore
// making the PID useless) is not expected to be a problem. Further
// more, using gtk/gdk as the model it would seem that not using a FQDN is
// not an issue for modern Xorg window managers.
os::Printer::log("Setting Xorg window manager Properties", ELL_DEBUG);
XSetWMProperties (XDisplay, XWindow, NULL, NULL, NULL, 0, NULL, NULL, NULL);
// Set the _NET_WM_PID window property according to the EWMH spec. _NET_WM_PID
// (in conjunction with WM_CLIENT_MACHINE) can be used by window managers to
// force a shutdown of an application if it doesn't respond to the destroy
// window message.
os::Printer::log("Setting Xorg _NET_WM_PID extended window manager property", ELL_DEBUG);
Atom NET_WM_PID = XInternAtom(XDisplay, "_NET_WM_PID", false);
pid_t pid = getpid();
XChangeProperty(XDisplay, XWindow, NET_WM_PID,
XA_CARDINAL, 32, PropModeReplace,
reinterpret_cast<unsigned char *>(&pid),1);
// Set the WM_CLIENT_LEADER window property here. Minetest has only one
// window and that window will always be the leader.
os::Printer::log("Setting Xorg WM_CLIENT_LEADER property", ELL_DEBUG);
Atom WM_CLIENT_LEADER = XInternAtom(XDisplay, "WM_CLIENT_LEADER", false);
XChangeProperty (XDisplay, XWindow, WM_CLIENT_LEADER,
XA_WINDOW, 32, PropModeReplace,
reinterpret_cast<unsigned char *>(&XWindow), 1);
#endif
}
#if defined(_IRR_COMPILE_WITH_X11_)
void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
{
@ -1178,6 +1248,50 @@ void CIrrDeviceLinux::setWindowCaption(const wchar_t* text)
}
//! Sets the window icon.
bool CIrrDeviceLinux::setWindowIcon(const video::IImage *img)
{
if (CreationParams.DriverType == video::EDT_NULL)
return false; // no display and window
u32 height = img->getDimension().Height;
u32 width = img->getDimension().Width;
size_t icon_buffer_len = 2 + height * width;
long *icon_buffer = new long[icon_buffer_len];
icon_buffer[0] = width;
icon_buffer[1] = height;
for (u32 x = 0; x < width; x++) {
for (u32 y = 0; y < height; y++) {
video::SColor col = img->getPixel(x, y);
long pixel_val = 0;
pixel_val |= (u8)col.getAlpha() << 24;
pixel_val |= (u8)col.getRed() << 16;
pixel_val |= (u8)col.getGreen() << 8;
pixel_val |= (u8)col.getBlue();
icon_buffer[2 + x + y * width] = pixel_val;
}
}
if (XDisplay == NULL) {
os::Printer::log("Could not find x11 display for setting its icon.", ELL_ERROR);
delete[] icon_buffer;
return false;
}
Atom net_wm_icon = XInternAtom(XDisplay, "_NET_WM_ICON", False);
Atom cardinal = XInternAtom(XDisplay, "CARDINAL", False);
XChangeProperty(XDisplay, XWindow, net_wm_icon, cardinal, 32, PropModeReplace,
(const unsigned char *)icon_buffer, icon_buffer_len);
delete[] icon_buffer;
return true;
}
//! notifies the device that it should close itself
void CIrrDeviceLinux::closeDevice()
{
@ -1866,6 +1980,28 @@ void CIrrDeviceLinux::clearSystemMessages()
#endif //_IRR_COMPILE_WITH_X11_
}
//! Get the display density in dots per inch.
float CIrrDeviceLinux::getDisplayDensity() const
{
#ifdef _IRR_COMPILE_WITH_X11_
if (XDisplay != NULL) {
/* try x direct */
int dh = DisplayHeight(XDisplay, 0);
int dw = DisplayWidth(XDisplay, 0);
int dh_mm = DisplayHeightMM(XDisplay, 0);
int dw_mm = DisplayWidthMM(XDisplay, 0);
if (dh_mm != 0 && dw_mm != 0) {
float dpi_height = floor(dh / (dh_mm * 0.039370) + 0.5);
float dpi_width = floor(dw / (dw_mm * 0.039370) + 0.5);
return std::max(dpi_height, dpi_width);
}
}
#endif //_IRR_COMPILE_WITH_X11_
return 0.0f;
}
void CIrrDeviceLinux::initXAtoms()
{
#ifdef _IRR_COMPILE_WITH_X11_

View File

@ -54,6 +54,9 @@ namespace irr
//! sets the caption of the window
void setWindowCaption(const wchar_t* text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
@ -120,6 +123,9 @@ namespace irr
return EIDT_X11;
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
#ifdef _IRR_COMPILE_WITH_X11_
// convert an Irrlicht texture to a X11 cursor
Cursor TextureToCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
@ -146,6 +152,8 @@ namespace irr
bool switchToFullscreen();
void setupTopLevelXorgWindow();
#ifdef _IRR_COMPILE_WITH_X11_
bool createInputContext();
void destroyInputContext();

View File

@ -136,6 +136,13 @@ ITimer* CIrrDeviceStub::getTimer()
}
//! Sets the window icon.
bool CIrrDeviceStub::setWindowIcon(const video::IImage *img)
{
return false;
}
//! Returns the version of the engine.
const char* CIrrDeviceStub::getVersion() const
{
@ -385,6 +392,12 @@ void CIrrDeviceStub::clearSystemMessages()
{
}
//! Get the display density in dots per inch.
float CIrrDeviceStub::getDisplayDensity() const
{
return 0.0f;
}
//! Checks whether the input device should take input from the IME
bool CIrrDeviceStub::acceptsIME()
{

View File

@ -71,6 +71,9 @@ namespace irr
//! Returns a pointer to the ITimer object. With it the current Time can be received.
ITimer* getTimer() override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! Returns the version of the engine.
const char* getVersion() const override;
@ -151,6 +154,9 @@ namespace irr
//! Remove all messages pending in the system message loop
void clearSystemMessages() override;
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
//! Resize the render window.
void setWindowSize(const irr::core::dimension2d<u32>& size) override {}

View File

@ -1112,6 +1112,26 @@ void CIrrDeviceWin32::setWindowCaption(const wchar_t* text)
}
//! Sets the window icon.
bool CIrrDeviceWin32::setWindowIcon(const video::IImage *img)
{
// Ignore the img, instead load the ICON from resource file
// (This is minetest-specific!)
const HICON hicon = LoadIcon(GetModuleHandle(NULL),
MAKEINTRESOURCE(130) // The ID of the ICON defined in
// winresource.rc
);
if (hicon) {
SendMessage(HWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hicon));
SendMessage(HWnd, WM_SETICON, ICON_SMALL,
reinterpret_cast<LPARAM>(hicon));
return true;
}
return false;
}
//! notifies the device that it should close itself
void CIrrDeviceWin32::closeDevice()
{
@ -1373,6 +1393,17 @@ void CIrrDeviceWin32::clearSystemMessages()
{}
}
//! Get the display density in dots per inch.
float CIrrDeviceWin32::getDisplayDensity() const
{
HDC hdc = GetDC(HWnd);
float dpi = GetDeviceCaps(hdc, LOGPIXELSX);
ReleaseDC(HWnd, hdc);
return dpi;
}
// Convert an Irrlicht texture to a Windows cursor
// Based on http://www.codeguru.com/cpp/w-p/win32/cursors/article.php/c4529/
HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot)

View File

@ -47,6 +47,9 @@ namespace irr
//! sets the caption of the window
void setWindowCaption(const wchar_t* text) override;
//! Sets the window icon.
bool setWindowIcon(const video::IImage *img) override;
//! returns if window is active. if not, nothing need to be drawn
bool isWindowActive() const override;
@ -96,6 +99,9 @@ namespace irr
return EIDT_WIN32;
}
//! Get the display density in dots per inch.
float getDisplayDensity() const override;
//! Compares to the last call of this function to return double and triple clicks.
//! \return Returns only 1,2 or 3. A 4th click will start with 1 again.
u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) override