mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-01 13:02:59 +02:00
Update to v106r69 release.
byuu says: The biggest change was improving WonderSwan emulation. With help from trap15, I tracked down a bug where I was checking the wrong bit for reverse DMA transfers. Then I also emulated VTOTAL to support variable refresh rate. Then I improved HyperVoice emulation which should be unsigned samples in three of four modes. That got Fire Lancer running great. I also rewrote the disassembler. The old one disassembled many instructions completely wrong, and deviated too much from any known x86 syntax. I also emulated some of the quirks of the V30 (two-byte POP into registers fails, SALC is just XLAT mirrored, etc) which probably don't matter unless someone tries to run code to verify it's a NEC CPU and not an Intel CPU, but hey, why not? I also put more work into the MSX skeleton, but it's still just a skeleton with no real emulation yet.
This commit is contained in:
@@ -10,6 +10,9 @@ auto pApplication::run() -> void {
|
||||
while(!Application::state().quit) {
|
||||
Application::doMain();
|
||||
processEvents();
|
||||
//avoid spinlooping the thread when there is no main loop ...
|
||||
//when there is one, Application::onMain() is expected to sleep when possible instead
|
||||
if(!Application::state().onMain) usleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +21,13 @@ auto pApplication::pendingEvents() -> bool {
|
||||
}
|
||||
|
||||
auto pApplication::processEvents() -> void {
|
||||
while(pendingEvents()) gtk_main_iteration_do(false);
|
||||
//GTK can sometimes return gtk_pending_events() == true forever,
|
||||
//no matter how many times gtk_main_iteration_do() is called.
|
||||
//implement a timeout to prevent hiro from hanging forever in this case.
|
||||
auto time = chrono::millisecond();
|
||||
while(pendingEvents() && chrono::millisecond() - time < 50) {
|
||||
gtk_main_iteration_do(false);
|
||||
}
|
||||
for(auto& window : state().windows) window->_synchronizeGeometry();
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,8 @@ auto pFont::size(PangoFontDescription* font, const string& text) -> Size {
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
int width = 0, height = 0;
|
||||
pango_layout_get_pixel_size(layout, &width, &height);
|
||||
g_object_unref((gpointer)layout);
|
||||
g_object_unref(layout);
|
||||
g_object_unref(context);
|
||||
return {width, height};
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ auto pFont::family(const string& family) -> string {
|
||||
#elif defined(DISPLAY_XORG)
|
||||
if(family == Font::Sans ) return "Sans";
|
||||
if(family == Font::Serif) return "Serif";
|
||||
if(family == Font::Mono ) return "Liberation Mono";
|
||||
if(family == Font::Mono ) return "Monospace";
|
||||
return family ? family : "Sans";
|
||||
#else
|
||||
return family;
|
||||
|
@@ -12,6 +12,9 @@ auto pSizable::minimumSize() const -> Size {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pSizable::setCollapsible(bool collapsible) -> void {
|
||||
}
|
||||
|
||||
auto pSizable::setGeometry(Geometry geometry) -> void {
|
||||
self().doSize();
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ struct pSizable : pObject {
|
||||
Declare(Sizable, Object)
|
||||
|
||||
virtual auto minimumSize() const -> Size;
|
||||
virtual auto setCollapsible(bool collapsible) -> void;
|
||||
virtual auto setGeometry(Geometry geometry) -> void;
|
||||
};
|
||||
|
||||
|
@@ -3,6 +3,9 @@
|
||||
namespace hiro {
|
||||
|
||||
static auto Timer_trigger(pTimer* p) -> signed {
|
||||
//prevent all timers from firing once the program has been terminated
|
||||
if(Application::state().quit) return false;
|
||||
|
||||
//timer may have been disabled prior to triggering, so check state
|
||||
if(p->self().enabled(true)) p->self().doActivate();
|
||||
|
||||
|
@@ -46,6 +46,24 @@ static auto Label_expose(GtkWidget* widget, GdkEvent* event, pLabel* p) -> int {
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto Label_mousePress(GtkWidget* widget, GdkEventButton* event, pLabel* p) -> int {
|
||||
switch(event->button) {
|
||||
case 1: p->self().doMousePress(Mouse::Button::Left); break;
|
||||
case 2: p->self().doMousePress(Mouse::Button::Middle); break;
|
||||
case 3: p->self().doMousePress(Mouse::Button::Right); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static auto Label_mouseRelease(GtkWidget* widget, GdkEventButton* event, pLabel* p) -> int {
|
||||
switch(event->button) {
|
||||
case 1: p->self().doMouseRelease(Mouse::Button::Left); break;
|
||||
case 2: p->self().doMouseRelease(Mouse::Button::Middle); break;
|
||||
case 3: p->self().doMouseRelease(Mouse::Button::Right); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
auto pLabel::construct() -> void {
|
||||
gtkWidget = gtk_event_box_new();
|
||||
subWidget = gtk_label_new("");
|
||||
@@ -57,6 +75,8 @@ auto pLabel::construct() -> void {
|
||||
setForegroundColor(state().foregroundColor);
|
||||
setText(state().text);
|
||||
|
||||
g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Label_mousePress), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Label_mouseRelease), (gpointer)this);
|
||||
#if HIRO_GTK==2
|
||||
g_signal_connect(G_OBJECT(subWidget), "expose-event", G_CALLBACK(Label_expose), (gpointer)this);
|
||||
#elif HIRO_GTK==3
|
||||
|
@@ -7,13 +7,7 @@ static auto SourceEdit_change(GtkTextBuffer*, pSourceEdit* p) -> void {
|
||||
}
|
||||
|
||||
static auto SourceEdit_move(GObject*, GParamSpec*, pSourceEdit* p) -> void {
|
||||
signed offset = 0;
|
||||
g_object_get(G_OBJECT(p->gtkSourceBuffer), "cursor-position", &offset, nullptr);
|
||||
|
||||
if(p->state().cursor.offset() != offset) {
|
||||
p->state().cursor.setOffset(offset);
|
||||
if(!p->locked()) p->self().doMove();
|
||||
}
|
||||
if(!p->locked()) p->self().doMove();
|
||||
}
|
||||
|
||||
auto pSourceEdit::construct() -> void {
|
||||
@@ -24,16 +18,16 @@ auto pSourceEdit::construct() -> void {
|
||||
gtk_scrolled_window_set_shadow_type(gtkScrolledWindow, GTK_SHADOW_ETCHED_IN);
|
||||
|
||||
gtkSourceLanguageManager = gtk_source_language_manager_get_default();
|
||||
gtkSourceLanguage = gtk_source_language_manager_get_language(gtkSourceLanguageManager, "cpp");
|
||||
gtkSourceLanguage = gtk_source_language_manager_get_language(gtkSourceLanguageManager, "");
|
||||
|
||||
gtkSourceStyleSchemeManager = gtk_source_style_scheme_manager_get_default();
|
||||
gtkSourceStyleScheme = gtk_source_style_scheme_manager_get_scheme(gtkSourceStyleSchemeManager, "oblivion");
|
||||
gtkSourceStyleScheme = gtk_source_style_scheme_manager_get_scheme(gtkSourceStyleSchemeManager, "classic");
|
||||
|
||||
gtkSourceBuffer = gtk_source_buffer_new(nullptr);
|
||||
gtkTextBuffer = GTK_TEXT_BUFFER(gtkSourceBuffer);
|
||||
gtk_source_buffer_set_highlight_matching_brackets(gtkSourceBuffer, true);
|
||||
gtk_source_buffer_set_highlight_syntax(gtkSourceBuffer, true);
|
||||
//gtk_source_buffer_set_language(gtkSourceBuffer, gtkSourceLanguage);
|
||||
gtk_source_buffer_set_language(gtkSourceBuffer, gtkSourceLanguage);
|
||||
gtk_source_buffer_set_style_scheme(gtkSourceBuffer, gtkSourceStyleScheme);
|
||||
|
||||
gtkSourceView = (GtkSourceView*)gtk_source_view_new_with_buffer(gtkSourceBuffer);
|
||||
@@ -55,6 +49,9 @@ auto pSourceEdit::construct() -> void {
|
||||
gtk_widget_show(gtkWidgetSourceView);
|
||||
|
||||
setEditable(state().editable);
|
||||
setLanguage(state().language);
|
||||
setNumbered(state().numbered);
|
||||
setScheme(state().scheme);
|
||||
setText(state().text);
|
||||
setWordWrap(state().wordWrap);
|
||||
|
||||
@@ -70,6 +67,23 @@ auto pSourceEdit::destruct() -> void {
|
||||
gtk_widget_destroy(gtkWidget);
|
||||
}
|
||||
|
||||
auto pSourceEdit::cursor() const -> Cursor {
|
||||
Cursor cursor;
|
||||
int offset = 0;
|
||||
g_object_get(G_OBJECT(gtkSourceBuffer), "cursor-position", &offset, nullptr);
|
||||
cursor.setOffset(offset);
|
||||
GtkTextIter start, end;
|
||||
if(gtk_text_buffer_get_selection_bounds(gtkTextBuffer, &start, &end)) {
|
||||
//if selecting text from left to right, the cursor may be ahead of the selection start ...
|
||||
//since hiro combines selection bounds (end-start) into length, move the offset to the start
|
||||
int origin = gtk_text_iter_get_offset(&start);
|
||||
cursor.setOffset(origin);
|
||||
int length = gtk_text_iter_get_offset(&end) - origin;
|
||||
cursor.setLength(length);
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
auto pSourceEdit::setCursor(Cursor cursor) -> void {
|
||||
lock();
|
||||
GtkTextIter offset, length;
|
||||
@@ -92,45 +106,33 @@ auto pSourceEdit::setFocused() -> void {
|
||||
gtk_widget_grab_focus(gtkWidgetSourceView);
|
||||
}
|
||||
|
||||
/*
|
||||
auto pSourceEdit::setPosition(signed position) -> void {
|
||||
lock();
|
||||
GtkTextIter iter;
|
||||
//note: iterators must be initialized via get_iter() before calling set_offset()
|
||||
gtk_text_buffer_get_end_iter(gtkTextBuffer, &iter);
|
||||
if(position >= 0) {
|
||||
gtk_text_iter_set_offset(&iter, position);
|
||||
} else {
|
||||
state().position = gtk_text_iter_get_offset(&iter);
|
||||
}
|
||||
gtk_text_buffer_place_cursor(gtkTextBuffer, &iter);
|
||||
auto mark = gtk_text_buffer_get_mark(gtkTextBuffer, "insert");
|
||||
gtk_text_view_scroll_mark_onscreen(gtkTextView, mark);
|
||||
unlock();
|
||||
auto pSourceEdit::setLanguage(const string& language) -> void {
|
||||
string name;
|
||||
if(language == "C") name = "c";
|
||||
if(language == "C++") name = "cpp";
|
||||
if(language == "Make") name = "makefile";
|
||||
gtkSourceLanguage = gtk_source_language_manager_get_language(gtkSourceLanguageManager, name);
|
||||
gtk_source_buffer_set_language(gtkSourceBuffer, gtkSourceLanguage);
|
||||
}
|
||||
|
||||
auto pSourceEdit::setSelected(Position selected) -> void {
|
||||
lock();
|
||||
GtkTextIter iter;
|
||||
gtk_text_buffer_get_end_iter(gtkTextBuffer, &iter);
|
||||
signed offset = gtk_text_iter_get_offset(&iter);
|
||||
if(selected.x() < 0 || selected.x() > offset) selected.setX(offset);
|
||||
if(selected.y() < 0 || selected.y() > offset) selected.setY(offset);
|
||||
state().selected = selected;
|
||||
GtkTextIter startIter;
|
||||
gtk_text_buffer_get_start_iter(gtkTextBuffer, &startIter);
|
||||
gtk_text_iter_set_offset(&startIter, selected.x());
|
||||
GtkTextIter endIter;
|
||||
gtk_text_buffer_get_end_iter(gtkTextBuffer, &endIter);
|
||||
gtk_text_iter_set_offset(&endIter, selected.y());
|
||||
gtk_text_buffer_select_range(gtkTextBuffer, &startIter, &endIter);
|
||||
unlock();
|
||||
auto pSourceEdit::setNumbered(bool numbered) -> void {
|
||||
gtk_source_view_set_show_line_numbers(gtkSourceView, numbered);
|
||||
}
|
||||
|
||||
auto pSourceEdit::setScheme(const string& requestedScheme) -> void {
|
||||
auto scheme = requestedScheme ? requestedScheme : "classic";
|
||||
gtkSourceStyleScheme = gtk_source_style_scheme_manager_get_scheme(gtkSourceStyleSchemeManager, scheme.downcase());
|
||||
if(!gtkSourceStyleScheme) gtkSourceStyleScheme = gtk_source_style_scheme_manager_get_scheme(gtkSourceStyleSchemeManager, "classic");
|
||||
gtk_source_buffer_set_style_scheme(gtkSourceBuffer, gtkSourceStyleScheme);
|
||||
}
|
||||
*/
|
||||
|
||||
auto pSourceEdit::setText(const string& text) -> void {
|
||||
lock();
|
||||
//prevent Ctrl+Z from undoing the newly assigned text ...
|
||||
//for instance, a text editor widget setting the initial document here
|
||||
gtk_source_buffer_begin_not_undoable_action(gtkSourceBuffer);
|
||||
gtk_text_buffer_set_text(gtkTextBuffer, text, -1);
|
||||
gtk_source_buffer_end_not_undoable_action(gtkSourceBuffer);
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
@@ -5,9 +5,13 @@ namespace hiro {
|
||||
struct pSourceEdit : pWidget {
|
||||
Declare(SourceEdit, Widget)
|
||||
|
||||
auto cursor() const -> Cursor;
|
||||
auto setCursor(Cursor cursor) -> void;
|
||||
auto setEditable(bool editable) -> void;
|
||||
auto setFocused() -> void override;
|
||||
auto setLanguage(const string& language) -> void;
|
||||
auto setNumbered(bool numbered) -> void;
|
||||
auto setScheme(const string& scheme) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setWordWrap(bool wordWrap) -> void;
|
||||
auto text() const -> string;
|
||||
|
@@ -294,30 +294,40 @@ auto pTableView::_doEdit(GtkCellRendererText* gtkCellRendererText, const char* p
|
||||
}
|
||||
}
|
||||
|
||||
auto pTableView::_doEvent(GdkEventButton* event) -> signed {
|
||||
GtkTreePath* path = nullptr;
|
||||
gtk_tree_view_get_path_at_pos(gtkTreeView, event->x, event->y, &path, nullptr, nullptr, nullptr);
|
||||
auto pTableView::_doEvent(GdkEventButton* gdkEvent) -> signed {
|
||||
if(gdkEvent->type == GDK_BUTTON_PRESS) {
|
||||
//detect when the empty space of the GtkTreeView is clicked; and clear the selection
|
||||
GtkTreePath* gtkPath = nullptr;
|
||||
gtk_tree_view_get_path_at_pos(gtkTreeView, gdkEvent->x, gdkEvent->y, >kPath, nullptr, nullptr, nullptr);
|
||||
if(!gtkPath) {
|
||||
//the first time a GtkTreeView widget is clicked, even if the empty space of the widget is clicked,
|
||||
//a "changed" signal will be sent after the "button-press-event", to activate the first item in the tree
|
||||
//this is undesirable, so set a flag to undo the next selection change during the "changed" signal
|
||||
suppressChange = true;
|
||||
if(gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) {
|
||||
gtk_tree_selection_unselect_all(gtkTreeSelection);
|
||||
for(auto& item : state().items) item->setSelected(false);
|
||||
self().doChange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(event->type == GDK_BUTTON_PRESS) {
|
||||
//when clicking in empty space below the last table view item; GTK+ does not deselect all items;
|
||||
//below code enables this functionality, to match behavior with all other UI toolkits (and because it's very convenient to have)
|
||||
if(path == nullptr && gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) {
|
||||
for(auto& item : state().items) item->setSelected(false);
|
||||
self().doChange();
|
||||
return true;
|
||||
if(gdkEvent->button == 3) {
|
||||
//multi-selection mode:
|
||||
//if multiple items are selected, and one item is right-clicked on (for a context menu), GTK clears selection on all other items
|
||||
//block this behavior so that onContext() handler can work on more than one selected item at a time
|
||||
if(gtkPath && gtk_tree_selection_path_is_selected(gtkTreeSelection, gtkPath)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
||||
//this check prevents the loss of selection on other items if the item under the mouse cursor is currently selected
|
||||
if(path && gtk_tree_selection_path_is_selected(gtkTreeSelection, path)) return true;
|
||||
}
|
||||
|
||||
if(event->type == GDK_BUTTON_RELEASE && event->button == 3) {
|
||||
//handle action during right-click release; as button-press-event is sent prior to selection update
|
||||
//without this, the callback handler would see the previous selection state instead
|
||||
self().doContext();
|
||||
return false;
|
||||
if(gdkEvent->type == GDK_BUTTON_RELEASE) {
|
||||
suppressChange = false;
|
||||
if(gdkEvent->button == 3) {
|
||||
//handle action during right-click release; as button-press-event is sent prior to selection update
|
||||
//without this, the callback handler would see the previous selection state instead
|
||||
self().doContext();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -365,6 +375,12 @@ auto pTableView::_doToggle(GtkCellRendererToggle* gtkCellRendererToggle, const c
|
||||
//this prevents firing an onChange event when the actual selection has not changed
|
||||
//this is particularly important for the motion-notify-event binding
|
||||
auto pTableView::_updateSelected() -> void {
|
||||
if(suppressChange) {
|
||||
suppressChange = false;
|
||||
gtk_tree_selection_unselect_all(gtkTreeSelection);
|
||||
return;
|
||||
}
|
||||
|
||||
vector<unsigned> selected;
|
||||
|
||||
GList* list = gtk_tree_selection_get_selected_rows(gtkTreeSelection, >kTreeModel);
|
||||
|
@@ -44,6 +44,7 @@ struct pTableView : pWidget {
|
||||
GtkListStore* gtkListStore = nullptr;
|
||||
GtkTreeModel* gtkTreeModel = nullptr;
|
||||
vector<uint> currentSelection;
|
||||
bool suppressChange = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -25,6 +25,8 @@ auto pTreeView::construct() -> void {
|
||||
gtkTreeView = GTK_TREE_VIEW(gtkWidgetChild);
|
||||
gtkTreeSelection = gtk_tree_view_get_selection(gtkTreeView);
|
||||
gtk_tree_view_set_headers_visible(gtkTreeView, false);
|
||||
gtk_tree_view_set_show_expanders(gtkTreeView, false);
|
||||
gtk_tree_view_set_level_indentation(gtkTreeView, 20);
|
||||
gtk_container_add(GTK_CONTAINER(gtkWidget), gtkWidgetChild);
|
||||
gtk_widget_show(gtkWidgetChild);
|
||||
|
||||
@@ -58,10 +60,19 @@ auto pTreeView::construct() -> void {
|
||||
g_signal_connect(G_OBJECT(gtkTreeSelection), "changed", G_CALLBACK(TreeView_change), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(gtkCellToggle), "toggled", G_CALLBACK(TreeView_toggle), (gpointer)this);
|
||||
|
||||
//Ctrl+F triggers a small popup window at the bottom of the GtkTreeView, which clears the currently selected item(s)
|
||||
//this is undesirable for amethyst, which uses the active item to display a document to edit, and binds Ctrl+F to a document find function
|
||||
//for now, disable GtkTreeView's interactive search: longer term, more thought will need to go into if this is ever desirable or not
|
||||
//gtk_tree_view_set_enable_search(gtkTreeView, false) does not work
|
||||
//gtk_tree_view_set_search_column(gtkTreeView, -1) does not work
|
||||
gtkEntry = (GtkEntry*)gtk_entry_new();
|
||||
gtk_tree_view_set_search_entry(gtkTreeView, gtkEntry);
|
||||
|
||||
pWidget::construct();
|
||||
}
|
||||
|
||||
auto pTreeView::destruct() -> void {
|
||||
gtk_widget_destroy(GTK_WIDGET(gtkEntry));
|
||||
gtk_widget_destroy(gtkWidgetChild);
|
||||
gtk_widget_destroy(gtkWidget);
|
||||
}
|
||||
@@ -105,24 +116,39 @@ auto pTreeView::_activatePath(GtkTreePath* gtkPath) -> void {
|
||||
}
|
||||
|
||||
auto pTreeView::_buttonEvent(GdkEventButton* gdkEvent) -> signed {
|
||||
GtkTreePath* gtkPath = nullptr;
|
||||
gtk_tree_view_get_path_at_pos(gtkTreeView, gdkEvent->x, gdkEvent->y, >kPath, nullptr, nullptr, nullptr);
|
||||
|
||||
if(gdkEvent->type == GDK_BUTTON_PRESS) {
|
||||
//detect when the empty space of the GtkTreeView is clicked; and clear the selection
|
||||
if(gtkPath == nullptr && gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) {
|
||||
gtk_tree_selection_unselect_all(gtkTreeSelection);
|
||||
state().selectedPath.reset();
|
||||
self().doChange();
|
||||
return true;
|
||||
GtkTreePath* gtkPath = nullptr;
|
||||
gtk_tree_view_get_path_at_pos(gtkTreeView, gdkEvent->x, gdkEvent->y, >kPath, nullptr, nullptr, nullptr);
|
||||
if(!gtkPath) {
|
||||
//the first time a GtkTreeView widget is clicked, even if the empty space of the widget is clicked,
|
||||
//a "changed" signal will be sent after the "button-press-event", to activate the first item in the tree
|
||||
//this is undesirable, so set a flag to undo the next selection change during the "changed" signal
|
||||
suppressChange = true;
|
||||
if(gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) {
|
||||
gtk_tree_selection_unselect_all(gtkTreeSelection);
|
||||
state().selectedPath.reset();
|
||||
self().doChange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(gdkEvent->button == 3) {
|
||||
//multi-selection mode: (not implemented in TreeView yet ... but code is here anyway for future use)
|
||||
//if multiple items are selected, and one item is right-clicked on (for a context menu), GTK clears selection on all other items
|
||||
//block this behavior so that onContext() handler can work on more than one selected item at a time
|
||||
if(gtkPath && gtk_tree_selection_path_is_selected(gtkTreeSelection, gtkPath)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(gdkEvent->type == GDK_BUTTON_RELEASE && gdkEvent->button == 3) {
|
||||
//handle right-click context menu
|
||||
//have to detect on button release instead of press; as GTK+ does not update new selection prior to press event
|
||||
self().doContext();
|
||||
return false;
|
||||
if(gdkEvent->type == GDK_BUTTON_RELEASE) {
|
||||
suppressChange = false;
|
||||
if(gdkEvent->button == 3) {
|
||||
//handle action during right-click release; as button-press-event is sent prior to selection update
|
||||
//without this, the callback handler would see the previous selection state instead
|
||||
self().doContext();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -173,6 +199,12 @@ auto pTreeView::_togglePath(string path) -> void {
|
||||
}
|
||||
|
||||
auto pTreeView::_updateSelected() -> void {
|
||||
if(suppressChange) {
|
||||
suppressChange = false;
|
||||
gtk_tree_selection_unselect_all(gtkTreeSelection);
|
||||
return;
|
||||
}
|
||||
|
||||
GtkTreeIter iter;
|
||||
if(gtk_tree_selection_get_selected(gtkTreeSelection, >kTreeModel, &iter)) {
|
||||
char* gtkPath = gtk_tree_model_get_string_from_iter(gtkTreeModel, &iter);
|
||||
|
@@ -27,6 +27,8 @@ struct pTreeView : pWidget {
|
||||
GtkCellRenderer* gtkCellToggle = nullptr;
|
||||
GtkCellRenderer* gtkCellPixbuf = nullptr;
|
||||
GtkCellRenderer* gtkCellText = nullptr;
|
||||
GtkEntry* gtkEntry = nullptr;
|
||||
bool suppressChange = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -329,7 +329,9 @@ auto pWindow::setGeometry(Geometry geometry) -> void {
|
||||
setMinimumSize(state().minimumSize);
|
||||
|
||||
auto time1 = chrono::millisecond();
|
||||
while(chrono::millisecond() - time1 < 20) Application::processEvents();
|
||||
while(chrono::millisecond() - time1 < 20) {
|
||||
Application::processEvents();
|
||||
}
|
||||
|
||||
gtk_window_resize(GTK_WINDOW(widget), geometry.width(), geometry.height() + _menuHeight() + _statusHeight());
|
||||
|
||||
@@ -627,7 +629,7 @@ auto pWindow::_synchronizeState() -> void {
|
||||
if(!gtk_widget_get_realized(widget)) return;
|
||||
|
||||
#if defined(DISPLAY_WINDOWS)
|
||||
auto window = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
|
||||
auto window = (HWND)GDK_WINDOW_HWND(gtk_widget_get_window(widget));
|
||||
|
||||
bool maximized = IsZoomed(window);
|
||||
bool minimized = IsIconic(window);
|
||||
|
Reference in New Issue
Block a user