Update to v106r39 release.

byuu says:

Changelog:

  - ruby/video: implement onUpdate() callback to signal when redraws are
    necessary
  - ruby/video/GLX,GLX2,XVideo,XShm: implement onUpdate() support
  - bsnes: implement Video::onUpdate() support to redraw Viewport icon
    as needed
  - bsnes: save RAM before ruby driver changes
  - sfc/sa1: clip signed multiplication to 32-bit [Jonas Quinn]
  - sfc/sa1: handle negative dividends in division [Jonas Quinn]
  - hiro/gtk3: a few improvements
  - bsnes: added empty stub video and audio settings panels
  - bsnes: restructured advanced settings panel
  - bsnes: experiment: input/hotkeys name column bolded and colored for
    increased visual distinction
  - bsnes: added save button to state manager
This commit is contained in:
Tim Allen 2018-06-10 18:07:19 +10:00
parent 15b67922b3
commit 91bb781b73
24 changed files with 183 additions and 58 deletions

View File

@ -13,7 +13,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.38";
static const string Version = "106.39";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";

View File

@ -415,19 +415,19 @@ auto SA1::writeIO(uint24 addr, uint8 data) -> void {
//(MAL) multiplicand / dividend low
case 0x2251: {
mmio.ma = (mmio.ma & 0xff00) | data;
mmio.ma.byte(0) = data;
return;
}
//(MAH) multiplicand / dividend high
case 0x2252: {
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
mmio.ma.byte(1) = data;
return;
}
//(MBL) multiplier / divisor low
case 0x2253: {
mmio.mb = (mmio.mb & 0xff00) | data;
mmio.mb.byte(0) = data;
return;
}
@ -435,21 +435,23 @@ auto SA1::writeIO(uint24 addr, uint8 data) -> void {
//multiplication / cumulative sum only resets MB
//division resets both MA and MB
case 0x2254: {
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
mmio.mb.byte(1) = data;
if(mmio.acm == 0) {
if(mmio.md == 0) {
//signed multiplication
mmio.mr = (int16)mmio.ma * (int16)mmio.mb;
mmio.mr = (uint32)((int16)mmio.ma * (int16)mmio.mb);
mmio.mb = 0;
} else {
//unsigned division
if(mmio.mb == 0) {
mmio.mr = 0;
} else {
int16 quotient = (int16)mmio.ma / (uint16)mmio.mb;
uint16 remainder = (int16)mmio.ma % (uint16)mmio.mb;
mmio.mr = (remainder << 16) | quotient;
int16 dividend = mmio.ma;
uint16 divisor = mmio.mb;
uint16 remainder = dividend >= 0 ? dividend % divisor : (dividend % divisor + divisor) % divisor;
uint16 quotient = (dividend - remainder) / divisor;
mmio.mr = remainder << 16 | quotient;
}
mmio.ma = 0;
mmio.mb = 0;
@ -457,8 +459,8 @@ auto SA1::writeIO(uint24 addr, uint8 data) -> void {
} else {
//sigma (accumulative multiplication)
mmio.mr += (int16)mmio.ma * (int16)mmio.mb;
mmio.overflow = (mmio.mr >= (1ULL << 40));
mmio.mr &= (1ULL << 40) - 1;
mmio.overflow = mmio.mr >> 40;
mmio.mr = (uint40)mmio.mr;
mmio.mb = 0;
}
return;

View File

@ -99,10 +99,12 @@ Presentation::Presentation() {
statusBar.setVisible(showStatusBar.checked());
if(visible()) resizeWindow();
});
inputSettings.setText("Input ...").onActivate([&] { settingsWindow->show(0); });
hotkeySettings.setText("Hotkeys ...").onActivate([&] { settingsWindow->show(1); });
pathSettings.setText("Paths ...").onActivate([&] { settingsWindow->show(2); });
advancedSettings.setText("Advanced ...").onActivate([&] { settingsWindow->show(3); });
videoSettings.setText("Video ...").onActivate([&] { settingsWindow->show(0); });
audioSettings.setText("Audio ...").onActivate([&] { settingsWindow->show(1); });
inputSettings.setText("Input ...").onActivate([&] { settingsWindow->show(2); });
hotkeySettings.setText("Hotkeys ...").onActivate([&] { settingsWindow->show(3); });
pathSettings.setText("Paths ...").onActivate([&] { settingsWindow->show(4); });
advancedSettings.setText("Advanced ...").onActivate([&] { settingsWindow->show(5); });
toolsMenu.setText("Tools").setVisible(false);
saveState.setText("Save State");
@ -171,7 +173,7 @@ Presentation::Presentation() {
#if defined(PLATFORM_MACOS)
Application::Cocoa::onAbout([&] { about.doActivate(); });
Application::Cocoa::onActivate([&] { setFocused(); });
Application::Cocoa::onPreferences([&] { settingsWindow->show(0); });
Application::Cocoa::onPreferences([&] { settingsWindow->show(2); });
Application::Cocoa::onQuit([&] { doClose(); });
#endif
}

View File

@ -49,6 +49,8 @@ struct Presentation : Window {
MenuCheckItem muteAudio{&settingsMenu};
MenuCheckItem showStatusBar{&settingsMenu};
MenuSeparator settingsSeparator{&settingsMenu};
MenuItem videoSettings{&settingsMenu};
MenuItem audioSettings{&settingsMenu};
MenuItem inputSettings{&settingsMenu};
MenuItem hotkeySettings{&settingsMenu};
MenuItem pathSettings{&settingsMenu};

View File

@ -77,6 +77,7 @@ Program::Program(string_vector arguments) {
auto Program::main() -> void {
updateMessage();
video->poll();
inputManager->poll();
inputManager->pollHotkeys();

View File

@ -8,6 +8,10 @@ auto Program::initializeVideoDriver() -> void {
presentation->clearViewport();
updateVideoShader();
}
video->onUpdate([&](uint width, uint height) {
if(!emulator->loaded()) presentation->clearViewport();
});
}
auto Program::initializeAudioDriver() -> void {

View File

@ -3,8 +3,9 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
setText("Advanced");
layout.setMargin(5);
driversLabel.setText("Drivers").setFont(Font().setBold());
videoDriverLabel.setText("Video Driver:");
videoDriverLabel.setText("Video:");
for(auto& driver : Video::availableDrivers()) {
ComboButtonItem item;
item.setText(driver);
@ -12,10 +13,6 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
if(video->driver() == driver) item.setSelected();
}
videoDriverOption.onChange([&] {
auto item = videoDriverOption.selected();
videoDriverChange.setEnabled(video->driver() != item.text());
});
videoDriverChange.setText("Change").setEnabled(false).onActivate([&] {
auto item = videoDriverOption.selected();
settings["Video/Driver"].setValue(item.text());
if(!emulator->loaded() || item.text() == "None" || MessageDialog(
@ -23,6 +20,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
"It is highly recommended you unload your game first to avoid data loss.\n"
"Do you wish to proceed with the video driver change now anyway?"
).setParent(*settingsWindow).question() == "Yes") {
program->save();
program->saveRecoveryState();
settings["Crashed"].setValue(true);
settings.save();
@ -39,11 +37,10 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
}
settings["Crashed"].setValue(false);
settings.save();
videoDriverChange.setEnabled(false);
}
});
audioDriverLabel.setText("Audio Driver:");
audioDriverLabel.setText("Audio:");
for(auto& driver : Audio::availableDrivers()) {
ComboButtonItem item;
item.setText(driver);
@ -51,10 +48,6 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
if(audio->driver() == driver) item.setSelected();
}
audioDriverOption.onChange([&] {
auto item = audioDriverOption.selected();
audioDriverChange.setEnabled(audio->driver() != item.text());
});
audioDriverChange.setText("Change").setEnabled(false).onActivate([&] {
auto item = audioDriverOption.selected();
settings["Audio/Driver"].setValue(item.text());
if(!emulator->loaded() || item.text() == "None" || MessageDialog(
@ -62,6 +55,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
"It is highly recommended you unload your game first to avoid data loss.\n"
"Do you wish to proceed with the audio driver change now anyway?"
).setParent(*settingsWindow).question() == "Yes") {
program->save();
program->saveRecoveryState();
settings["Crashed"].setValue(true);
settings.save();
@ -78,11 +72,10 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
}
settings["Crashed"].setValue(false);
settings.save();
audioDriverChange.setEnabled(false);
}
});
inputDriverLabel.setText("Input Driver:");
inputDriverLabel.setText("Input:");
for(auto& driver : Input::availableDrivers()) {
ComboButtonItem item;
item.setText(driver);
@ -90,10 +83,6 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
if(input->driver() == driver) item.setSelected();
}
inputDriverOption.onChange([&] {
auto item = inputDriverOption.selected();
inputDriverChange.setEnabled(input->driver() != item.text());
});
inputDriverChange.setText("Change").setEnabled(false).onActivate([&] {
auto item = inputDriverOption.selected();
settings["Input/Driver"].setValue(item.text());
if(!emulator->loaded() || item.text() == "None" || MessageDialog(
@ -101,6 +90,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
"It is highly recommended you unload your game first to avoid data loss.\n"
"Do you wish to proceed with the input driver change now anyway?"
).setParent(*settingsWindow).question() == "Yes") {
program->save();
program->saveRecoveryState();
settings["Crashed"].setValue(true);
settings.save();
@ -117,7 +107,6 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
}
settings["Crashed"].setValue(false);
settings.save();
inputDriverChange.setEnabled(false);
}
});
}

View File

@ -0,0 +1,4 @@
AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) {
setIcon(Icon::Device::Speaker);
setText("Audio");
}

View File

@ -34,7 +34,7 @@ auto HotkeySettings::reloadMappings() -> void {
);
for(auto& hotkey : inputManager->hotkeys) {
mappingList.append(TableViewItem()
.append(TableViewCell().setText(hotkey.name))
.append(TableViewCell().setText(hotkey.name).setFont(Font().setBold()).setBackgroundColor({240, 240, 255}))
.append(TableViewCell())
);
}

View File

@ -98,7 +98,7 @@ auto InputSettings::reloadMappings() -> void {
);
for(auto& mapping : activeDevice().mappings) {
mappingList.append(TableViewItem()
.append(TableViewCell().setText(mapping.name))
.append(TableViewCell().setText(mapping.name).setFont(Font().setBold()).setBackgroundColor({240, 240, 255}))
.append(TableViewCell())
);
}
@ -111,6 +111,7 @@ auto InputSettings::refreshMappings() -> void {
for(auto& mapping : activeDevice().mappings) {
mappingList.item(index++).cell(1).setText(mapping.displayName());
}
Application::processEvents();
mappingList.resizeColumns();
}

View File

@ -1,4 +1,6 @@
#include "../bsnes.hpp"
#include "video.cpp"
#include "audio.cpp"
#include "input.cpp"
#include "hotkeys.cpp"
#include "paths.cpp"

View File

@ -3,6 +3,14 @@ struct Settings : Markup::Node {
auto save() -> void;
};
struct VideoSettings : TabFrameItem {
VideoSettings(TabFrame*);
};
struct AudioSettings : TabFrameItem {
AudioSettings(TabFrame*);
};
struct InputSettings : TabFrameItem {
InputSettings(TabFrame*);
auto updateControls() -> void;
@ -99,18 +107,14 @@ struct AdvancedSettings : TabFrameItem {
public:
VerticalLayout layout{this};
HorizontalLayout videoDriverLayout{&layout, Size{~0, 0}};
Label videoDriverLabel{&videoDriverLayout, Size{75, 0}};
ComboButton videoDriverOption{&videoDriverLayout, Size{~0, 0}};
Button videoDriverChange{&videoDriverLayout, Size{80, 0}};
HorizontalLayout audioDriverLayout{&layout, Size{~0, 0}};
Label audioDriverLabel{&audioDriverLayout, Size{75, 0}};
ComboButton audioDriverOption{&audioDriverLayout, Size{~0, 0}};
Button audioDriverChange{&audioDriverLayout, Size{80, 0}};
HorizontalLayout inputDriverLayout{&layout, Size{~0, 0}};
Label inputDriverLabel{&inputDriverLayout, Size{75, 0}};
ComboButton inputDriverOption{&inputDriverLayout, Size{~0, 0}};
Button inputDriverChange{&inputDriverLayout, Size{80, 0}};
Label driversLabel{&layout, Size{~0, 0}, 2};
HorizontalLayout driverLayout{&layout, Size{~0, 0}};
Label videoDriverLabel{&driverLayout, Size{0, 0}};
ComboButton videoDriverOption{&driverLayout, Size{~0, 0}};
Label audioDriverLabel{&driverLayout, Size{0, 0}};
ComboButton audioDriverOption{&driverLayout, Size{~0, 0}};
Label inputDriverLabel{&driverLayout, Size{0, 0}};
ComboButton inputDriverOption{&driverLayout, Size{~0, 0}};
};
struct SettingsWindow : Window {
@ -121,6 +125,8 @@ struct SettingsWindow : Window {
public:
VerticalLayout layout{this};
TabFrame panel{&layout, Size{~0, ~0}};
VideoSettings video{&panel};
AudioSettings audio{&panel};
InputSettings input{&panel};
HotkeySettings hotkeys{&panel};
PathSettings paths{&panel};

View File

@ -0,0 +1,4 @@
VideoSettings::VideoSettings(TabFrame* parent) : TabFrameItem(parent) {
setIcon(Icon::Device::Display);
setText("Video");
}

View File

@ -75,6 +75,7 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) {
stateList.onChange([&] {
auto batched = stateList.batched();
loadButton.setEnabled(batched.size() == 1);
saveButton.setEnabled(batched.size() == 1);
editButton.setEnabled(batched.size() == 1);
removeButton.setEnabled(batched.size() >= 1);
});
@ -84,6 +85,11 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) {
}
});
saveButton.setText("Save").onActivate([&] {
if(auto item = stateList.selected()) {
program->saveState(item.cell(0).text());
}
});
addButton.setText("Add").onActivate([&] {
stateWindow->show();
});
editButton.setText("Edit").onActivate([&] {

View File

@ -100,8 +100,9 @@ public:
TableView stateList{&layout, Size{~0, ~0}};
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
Button loadButton{&controlLayout, Size{80, 0}};
Widget spacer{&controlLayout, Size{~0, 0}};
Button saveButton{&controlLayout, Size{80, 0}};
Widget spacer{&controlLayout, Size{~0, 0}};
Button addButton{&controlLayout, Size{80, 0}};
Button editButton{&controlLayout, Size{80, 0}};
Button removeButton{&controlLayout, Size{80, 0}};
};

View File

@ -10,6 +10,11 @@ GtkSelectionData* data, unsigned type, unsigned timestamp, pCanvas* p) -> void {
p->self().doDrop(paths);
}
static auto Canvas_draw(GtkWidget* widget, cairo_t* context, pCanvas* p) -> signed {
p->_onDraw(context);
return true;
}
static auto Canvas_expose(GtkWidget* widget, GdkEventExpose* event, pCanvas* p) -> signed {
p->_onExpose(event);
return true;
@ -59,7 +64,11 @@ auto pCanvas::construct() -> void {
g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Canvas_mousePress), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Canvas_mouseRelease), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Canvas_drop), (gpointer)this);
#if HIRO_GTK==2
g_signal_connect(G_OBJECT(gtkWidget), "expose-event", G_CALLBACK(Canvas_expose), (gpointer)this);
#elif HIRO_GTK==3
g_signal_connect(G_OBJECT(gtkWidget), "draw", G_CALLBACK(Canvas_draw), (gpointer)this);
#endif
g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Canvas_mouseLeave), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Canvas_mouseMove), (gpointer)this);
@ -106,7 +115,36 @@ auto pCanvas::update() -> void {
_redraw();
}
auto pCanvas::_onDraw(cairo_t* context) -> void {
#if HIRO_GTK==3
int sx = 0, sy = 0, dx = 0, dy = 0;
int width = surfaceWidth, height = surfaceHeight;
auto geometry = pSizable::state().geometry;
if(width <= geometry.width()) {
sx = 0;
dx = (geometry.width() - width) / 2;
} else {
sx = (width - geometry.width()) / 2;
dx = 0;
}
if(height <= geometry.height()) {
sy = 0;
dy = (geometry.height() - height) / 2;
} else {
sy = (height - geometry.height()) / 2;
dy = 0;
}
//TODO: support non-zero sx,sy
gdk_cairo_set_source_pixbuf(context, surface, dx, dy);
cairo_paint(context);
#endif
}
auto pCanvas::_onExpose(GdkEventExpose* expose) -> void {
#if HIRO_GTK==2
if(surface == nullptr) return;
int sx = 0, sy = 0, dx = 0, dy = 0;
@ -132,10 +170,7 @@ auto pCanvas::_onExpose(GdkEventExpose* expose) -> void {
height = geometry.height();
}
#if HIRO_GTK==2
gdk_draw_pixbuf(gtk_widget_get_window(gtkWidget), nullptr, surface, sx, sy, dx, dy, width, height, GDK_RGB_DITHER_NONE, 0, 0);
#elif HIRO_GTK==3
//TODO: use cairo here, but how? no examples show to use sx, sy
#endif
}

View File

@ -13,6 +13,7 @@ struct pCanvas : pWidget {
auto setIcon(const image& icon) -> void;
auto update() -> void;
auto _onDraw(cairo_t* context) -> void;
auto _onExpose(GdkEventExpose* event) -> void;
auto _rasterize() -> void;
auto _redraw() -> void;

View File

@ -10,6 +10,10 @@ GtkSelectionData* data, unsigned type, unsigned timestamp, pViewport* p) -> void
p->self().doDrop(paths);
}
static auto Viewport_draw(GtkWidget* widget, cairo_t* context, pViewport* p) -> signed {
return true;
}
static auto Viewport_expose(GtkWidget* widget, GdkEventExpose* event) -> signed {
return true;
}
@ -59,7 +63,11 @@ auto pViewport::construct() -> void {
g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Viewport_mousePress), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Viewport_dropEvent), (gpointer)this);
#if HIRO_GTK==2
g_signal_connect(G_OBJECT(gtkWidget), "expose-event", G_CALLBACK(Viewport_expose), (gpointer)this);
#elif HIRO_GTK==3
g_signal_connect(G_OBJECT(gtkWidget), "draw", G_CALLBACK(Viewport_draw), (gpointer)this);
#endif
g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Viewport_mouseMove), (gpointer)this);

View File

@ -30,7 +30,6 @@ static auto Window_draw(GtkWidget* widget, cairo_t* context, pWindow* p) -> sign
cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
cairo_paint(context);
cairo_destroy(context);
}
return false;
}
@ -39,7 +38,8 @@ static auto Window_draw(GtkWidget* widget, cairo_t* context, pWindow* p) -> sign
static auto Window_expose(GtkWidget* widget, GdkEvent* event, pWindow* p) -> signed {
if(auto color = p->state().backgroundColor) {
cairo_t* context = gdk_cairo_create(gtk_widget_get_window(widget));
return Window_draw(widget, context, p);
Window_draw(widget, context, p);
cairo_destroy(context);
}
return false;
}

View File

@ -33,9 +33,16 @@ struct Video {
virtual auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { return false; }
virtual auto unlock() -> void {}
virtual auto output() -> void {}
virtual auto poll() -> void {}
auto onUpdate(const nall::function<void (uint, uint)>& callback) { _onUpdate = callback; }
auto doUpdate(uint width, uint height) -> void {
if(_onUpdate) return _onUpdate(width, height);
}
private:
nall::string _driver;
nall::function<void (uint, uint)> _onUpdate;
};
struct Audio {
@ -100,7 +107,7 @@ struct Input {
auto onChange(const nall::function<void (nall::shared_pointer<nall::HID::Device>, uint, uint, int16_t, int16_t)>& callback) { _onChange = callback; }
auto doChange(nall::shared_pointer<nall::HID::Device> device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void {
if(_onChange) _onChange(device, group, input, oldValue, newValue);
if(_onChange) return _onChange(device, group, input, oldValue, newValue);
}
private:

View File

@ -91,6 +91,18 @@ struct VideoGLX : Video, OpenGL {
if(_doubleBuffer) glXSwapBuffers(_display, _glXWindow);
}
auto poll() -> void {
while(XPending(_display)) {
XEvent event;
XNextEvent(_display, &event);
if(event.type == Expose) {
XWindowAttributes attributes;
XGetWindowAttributes(_display, _window, &attributes);
doUpdate(attributes.width, attributes.height);
}
}
}
private:
auto initialize() -> bool {
terminate();
@ -136,6 +148,7 @@ private:
/* x = */ 0, /* y = */ 0, windowAttributes.width, windowAttributes.height,
/* border_width = */ 0, vi->depth, InputOutput, vi->visual,
CWColormap | CWBorderPixel, &attributes);
XSelectInput(_display, _window, ExposureMask);
XSetWindowBackground(_display, _window, /* color = */ 0);
XMapWindow(_display, _window);
XFlush(_display);

View File

@ -111,6 +111,18 @@ struct VideoGLX2 : Video {
if(_isDoubleBuffered) glXSwapBuffers(_display, _glXWindow);
}
auto poll() -> void {
while(XPending(_display)) {
XEvent event;
XNextEvent(_display, &event);
if(event.type == Expose) {
XWindowAttributes attributes;
XGetWindowAttributes(_display, _window, &attributes);
doUpdate(attributes.width, attributes.height);
}
}
}
private:
auto initialize() -> bool {
terminate();
@ -147,6 +159,7 @@ private:
attributes.border_pixel = 0;
_window = XCreateWindow(_display, (Window)_context, 0, 0, windowAttributes.width, windowAttributes.height,
0, vi->depth, InputOutput, vi->visual, CWColormap | CWBorderPixel, &attributes);
XSelectInput(_display, _window, ExposureMask);
XSetWindowBackground(_display, _window, 0);
XMapWindow(_display, _window);
XFlush(_display);

View File

@ -88,12 +88,24 @@ struct VideoXShm : Video {
XFlush(_display);
}
auto poll() -> void override {
while(XPending(_display)) {
XEvent event;
XNextEvent(_display, &event);
if(event.type == Expose) {
XWindowAttributes attributes;
XGetWindowAttributes(_display, _window, &attributes);
doUpdate(attributes.width, attributes.height);
}
}
}
private:
auto initialize() -> bool {
terminate();
if(!_context) return false;
_display = XOpenDisplay(0);
_display = XOpenDisplay(nullptr);
_screen = DefaultScreen(_display);
XWindowAttributes getAttributes;
@ -109,12 +121,12 @@ private:
XSetWindowAttributes setAttributes = {};
setAttributes.border_pixel = 0;
setAttributes.event_mask = ExposureMask;
_window = XCreateWindow(_display, (Window)_context,
0, 0, 256, 256, 0,
getAttributes.depth, InputOutput, getAttributes.visual,
CWBorderPixel, &setAttributes
);
XSelectInput(_display, _window, ExposureMask);
XSetWindowBackground(_display, _window, 0);
XMapWindow(_display, _window);
XFlush(_display);

View File

@ -91,6 +91,18 @@ struct VideoXVideo : Video {
true);
}
auto poll() -> void {
while(XPending(_display)) {
XEvent event;
XNextEvent(_display, &event);
if(event.type == Expose) {
XWindowAttributes attributes;
XGetWindowAttributes(_display, _window, &attributes);
doUpdate(attributes.width, attributes.height);
}
}
}
private:
auto initialize() -> bool {
terminate();
@ -148,11 +160,11 @@ private:
XSetWindowAttributes attributes;
attributes.colormap = _colormap;
attributes.border_pixel = 0;
attributes.event_mask = StructureNotifyMask;
_window = XCreateWindow(_display, /* parent = */ (Window)_context,
/* x = */ 0, /* y = */ 0, window_attributes.width, window_attributes.height,
/* border_width = */ 0, _depth, InputOutput, visualInfo->visual,
CWColormap | CWBorderPixel | CWEventMask, &attributes);
XSelectInput(_display, _window, ExposureMask);
XFree(visualInfo);
XSetWindowBackground(_display, _window, /* color = */ 0);
XMapWindow(_display, _window);