View Single Post
daperl's Avatar
Posts: 2,427 | Thanked: 2,986 times | Joined on Dec 2007
#80
@qwerty12

Here's the demo. It works in Kubuntu 8.10 i386 and in Diablo, so I'm guessing it will work in Mer. I'm letting GTK position the menus at the moment because it's doing a decent job. If you would rather have more control of the menu placement that's easy to take care of. Also, I'm currently doing nothing about the icon's change-of-state; it always looks like it's inactive in the Diablo statusbar sense. Simple to remedy. Because this is a demo, these similar 3 lines from the previous tap_and_hold function are most likely what you want for a real application:

Code:
            self.press_event.button = 3
            self.press_event.time = gtk.get_current_event_time()
            self.on_any_event(self.press_event)
Code:
#! /usr/bin/env python

import gobject
import gtk

class qwerty12():
    tah_timeout = 1000

    def __init__(self):
        self.screen = None
        self.root_win = None
        self.rec = None
        self.mapped = False
        self.is_icon_on_top = True
        self.press_event = None
        self.last_tah_press_num = -1
        self.press_num = 0
        self.pressing = False
        gtk.gdk.event_handler_set(self.on_any_event)
        self.i = 5
        self.statusIcon = gtk.StatusIcon()
        self.statusIcon.set_from_stock(gtk.STOCK_CONNECT)
        self.clicked_menu = gtk.Menu()
        self.clicked_menu.__dict__['mapped'] = False
        self.clicked_menu.connect('map-event', self.on_map_menu, True)
        self.clicked_menu.connect('unmap-event', self.on_map_menu, False)
        self.clicked_menu.append(gtk.MenuItem('Clicked 1'))
        self.clicked_menu.append(gtk.MenuItem('Clicked 2'))
        self.clicked_menu.append(gtk.MenuItem('Clicked 3'))
        i = 1
        for c in self.clicked_menu.get_children():
            c.connect('activate', self.on_activate_mi, 'clicked '+str(i))
            c.connect('enter-notify-event', self.on_enter_mi, 'clicked '+str(i))
            i += 1
        self.clicked_menu.show_all()
        gtk.status_icon_position_menu(self.clicked_menu, self.statusIcon)
        self.tah_menu = gtk.Menu()
        self.tah_menu.__dict__['mapped'] = False
        self.tah_menu.connect('map-event', self.on_map_menu, True)
        self.tah_menu.connect('unmap-event', self.on_map_menu, False)
        self.tah_menu.append(gtk.MenuItem('TAH 1'))
        self.tah_menu.append(gtk.MenuItem('TAH 2'))
        self.tah_menu.append(gtk.MenuItem('TAH 3'))
        self.tah_menu.append(gtk.MenuItem('TAH 4'))
        self.tah_menu.append(gtk.MenuItem('TAH 5'))
        self.tah_menu.append(gtk.MenuItem('TAH 6'))
        self.tah_menu.append(gtk.MenuItem('TAH 7'))
        i = 1
        for c in self.tah_menu.get_children():
            c.connect('activate', self.on_activate_mi, 'tah '+str(i))
            c.connect('enter-notify-event', self.on_enter_mi, 'tah '+str(i))
            i += 1
        self.tah_menu.show_all()
        gtk.status_icon_position_menu(self.tah_menu, self.statusIcon)

    def on_activate_mi(self, mi, t):
        print 'activate mi',t,mi.get_name()
    def on_enter_mi(self, mi, event, t):
        #print 'enter mi',t
        p = mi.get_parent()
        p.deselect()
        p.select_item(mi)
    def on_map_menu(self, m, event, b):
        #print 'map menu before after',m.mapped,b
        m.mapped = b
    def tap_and_hold(self, event, tah_press_num):
        print 'num self.press_num',tah_press_num,self.press_num
        if self.pressing and tah_press_num == self.press_num:
            rec = self.rec
            x, y, m = self.root_win.get_pointer()
            print 'tah x y w h',x,y,rec.x,rec.y,rec.width,rec.height
            self.last_tah_press_num = tah_press_num
            self.clicked_menu.popdown()
            #self.tah_menu.popup(None,None,gtk.status_icon_position_menu,1,gtk.get_current_event_time(),self.statusIcon)
            self.tah_menu.popup(None,None,gtk.status_icon_position_menu,1,event.time+self.tah_timeout,self.statusIcon)
        return False

    def is_icon_event(self):
        #x, y, m = self.root_win.get_pointer()
        self.screen, self.rec, o = self.statusIcon.get_geometry()
        x, y, m = self.screen.get_root_window().get_pointer()
        dx = x - self.rec.x
        dy = y - self.rec.y
        return dx >=0 and dx <= self.rec.width and dy >= 0 and dy <= self.rec.height

    def set_menu_pos(self, menu):
        mw, mh = menu.get_toplevel().get_size()
        x = 0
        y = 0
        if self.is_icon_on_top:
            pass
        else:
            #x = self.rec.x + self.rec.width - mw
            x = self.rec.x - mw
            y = self.rec.y - mh - 10
        print 'clicked menu x y',x,y,mw,mh
        return (x, y, False)

    def on_any_event(self, event):
        if event.type == gtk.gdk.MOTION_NOTIFY: return
        #print 'event',event.type
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.mapped and event.button == 1 and self.is_icon_event():
                self.press_event = event.copy()
                self.pressing = True
                self.press_num += 1
                gobject.timeout_add(self.tah_timeout, self.tap_and_hold, event, self.press_num)
            #print 'press',event.x,event.y,event.button
        elif event.type == gtk.gdk.BUTTON_RELEASE:
            self.pressing = False
            #print 'button release num last_num',self.press_num,self.last_tah_press_num
            #print 'release tma visible',self.tah_menu.props.visible
            if event.button == 1 and self.is_icon_event() and\
            self.press_num != self.last_tah_press_num and not self.tah_menu.mapped:
                if self.clicked_menu.mapped:
                    self.clicked_menu.popdown()
                else:
                    #self.clicked_menu.popup(None,None,self.set_menu_pos,1,event.time)
                    self.clicked_menu.popup(None,None,gtk.status_icon_position_menu,1,event.time,self.statusIcon)
                #print 'time for clicked menu'
        elif event.type == gtk.gdk.LEAVE_NOTIFY:
            self.pressing = False
        elif event.type == gtk.gdk.MAP:
            if not self.mapped:
                self.screen, rec, o = self.statusIcon.get_geometry()
                self.root_win = self.screen.get_root_window()
                print 'rec',rec.x,rec.y,rec.width,rec.height
                self.rec = rec
                self.mapped = True
                self.is_icon_on_top = rec.y < rec.height
        gtk.main_do_event(event)

if __name__ == "__main__":
    q12 = qwerty12()
    gtk.main()
__________________
N9: Go white or go home
 

The Following 3 Users Say Thank You to daperl For This Useful Post: