1
votes

I have a custom GtkDrawingArea-based widget inside a GtkHeaderBar which is basically a slider that receives mouse clicks and moves. Everything worked fine in GTK 3.14-something, but in 3.22 things went south: when I click and drag inside my widget, GTK thinks I'm trying to drag the window (first few pixels go to the widget, but then the window takes over).

How do I prevent mouse events from propagating to the window?

Both motion-notify-event and button-press-event return TRUE (that did the trick in 3.14, not anymore).

g_sinal_connect(Something->DrawingArea, "motion-notify-event", G_CALLBACK(Something_motion), Something);
g_signal_connect(Something->DrawingArea, "button-press-event", G_CALLBACK(Something_press), Something);
1
Are there any handler(s) installed on your drawing elements which are capturing events? Remember you have to end those handlers with FALSE to allow the events to the underlying widgets. How do you draw your custom widget?jcoppens
@jcoppens, I have 3 handlers: motion-notify-event, button-press-event and button-release-event. I want to PREVENT them from propagating to the underlying widget (GtkHeaderBar, to be precise), which is why I return TRUE. It used to work, but stopped working in the newer GTK versions. I draw using Cairo in the "draw" callback.NK22

1 Answers

1
votes

Answering as an answer, as I can't input code into the 'comments'.

I suspect you have to enable the EventMask corresponding to the DrawingArea. This is somewhat different from other widgets, I guess.

Below is a small demo program in Python3 (this basically connects directly to the Gtk3.2x libraries, so should be similar to what you want to do in C.

Changing the return True to False in area_button_press() will make it transparent to the button_press_event, as expected. Commenting the line with ...add_events(Gdk.EventMask.BUTTON_PRESS_MASK) is needed in the code to make the button-press-event to be recognized at all:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#  test_headerbar_events.py
#
#  Copyright 2017 John Coppens <[email protected]>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#


from gi.repository import Gtk, Gdk

class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connect("destroy", lambda x: Gtk.main_quit())
        self.set_default_size(200, -1)

        hdrbar = Gtk.HeaderBar(title = "Header bar")
        hdrbar.connect("button-press-event", self.hdrbar_button_press)

        drawing_area = Gtk.DrawingArea()
        drawing_area.set_size_request(30, 30)
        drawing_area.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        drawing_area.connect("button-press-event", self.area_button_press)

        frame = Gtk.Frame()
        frame.add(drawing_area)

        hdrbar.pack_start(frame)

        self.add(hdrbar)
        self.show_all()

    def area_button_press(self, btn, event):
        print("Button pressed on Drawing Area")
        return True

    def hdrbar_button_press(self, btn, event):
        print("Button pressed on Header Bar")
        return False


    def run(self):
        Gtk.main()


def main(args):
    mainwdw = MainWindow()
    mainwdw.run()

    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

EDIT: If you use set_titlebar(), the events seem to go directly to the windowmanager (which would probably be what you want normally), instead of the underlying window. If you want to control (block) the movement of the window you could

  • Not use set_titlebar() and use set_decorations(False), which will hide the window's titlebar and show your headerbar at the top. Then the events will be controllable. Use a VBox to store your headerbar and the content of the rest of the window.

  • Of course. this way you will have to implement window dragging yourself (which is not too complicated). If needed, have a look at the GUI frontend I made for the Wcalc calculator (years ago - you may need to tweak the Gtk calls),