Uc@sdZddlZejdddlZddlZed\ZZZed\Z Z Z dZ dej fdYZdejfd YZd ejfd YZd Zed krendS(sChange Display Demonstrates migrating a window between different displays and screens. A display is a mouse and keyboard with some number of associated monitors. A screen is a set of monitors grouped into a single physical work area. The neat thing about having multiple displays is that they can be on a completely separate computers, as long as there is a network connection to the computer where the application is running. Only some of the windowing systems where GTK+ runs have the concept of multiple displays and screens. (The X Window System is the main example.) Other windowing systems can only handle one keyboard and mouse, and combine all monitors into a single screen. This is a moderately complex example, and demonstrates: - Tracking the currently open displays and screens - Changing the screen for a window - Letting the user choose a window by clicking on it - Using GtkListStore and GtkTreeView - Using GtkDialog iNs2.0icCs;|jd}|r%|j}n|r7|jp:dS(s@ Finds the toplevel window under the mouse pointer, if any. iN(tget_window_at_pointert get_user_datat get_topleveltNone(tdisplaytpointer_windowtwidget((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pytfind_toplevel_at_pointer.stQueryForToplevelcBs)eZdZdZdZdZRS(s Asks the user to click on a window, then waits for them click the mouse. When the mouse is released, returns the toplevel window under the pointer, or NULL, if there is none. cCstjj|tj|j||jt|jtjtj }|j tj |j |tj |}|jdd|j ||jdS(Ni (tgtktWindowt__init__t WINDOW_POPUPt set_screent set_modaltTruet set_positiontWIN_POS_CENTERtFrametset_shadow_typet SHADOW_OUTtaddtLabelt set_paddingtshow_all(tselftscreentprompttframetlabel((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR As     cCs|jj}tjj|tjj}tj}tjj|j t tjj d|tjj krt |_|jd|jx |jt kr|jtqWt|}||krd}qn|jtjj|S(Nsbutton-release-event(t get_screent get_displayR tgdktCursort CROSSHAIRtgobjecttmain_context_defaultt pointer_grabtwindowtFalsetBUTTON_RELEASE_MASKRt GRAB_SUCCESSt query_clickedtconnecttbutton_release_event_cbt iterationRRtdestroytflush(RRtcursort main_contextttoplevel((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pytrunQs !      cCs t|_tS(N(RR*(Rtwinreftevent((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR,ks (t__name__t __module__t__doc__R R3R,(((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR;s  tLeftAlignButtoncBseZdZdZRS(s If we have a stack of buttons, it often looks better if their contents are left-aligned, rather than centered. This class creates a button and left-aligns it contents. cCs7tjj|||jd}|jdddS(Nigg?(R tButtonR t get_childrent set_alignment(RRtchild((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR us(R6R7R8R (((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR9pstChangeDisplayDemocBseZdZdZdZdZdZdZddZ dZ dZ dZ dZ dZdZdZdZd Zd Zd Zd Zd ZdZdZdZRS(c Cs<tjj|d|tjtjtjdtjf|jddy|j|j Wn$t k r|j ddnX|j d|j |j d|j tjtd}|jd |jj|ttd |j}|j|ttd |j}|j|ttd |j|jdS( NsChange Screen or displaytChangei,iR.cWs tjS(N(R t main_quit(tw((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pytstresponseiii(R tDialogR tDIALOG_NO_SEPARATORt STOCK_CLOSEtRESPONSE_CLOSEt RESPONSE_OKtset_default_sizeR RtAttributeErrorR+t response_cbt destroy_cbtVBoxR'tset_border_widthtvboxt pack_startRt(_ChangeDisplayDemo__create_display_framet'_ChangeDisplayDemo__create_screen_framet'_ChangeDisplayDemo__initialize_displaysR(RtparentROR((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR s(      cCsbtjj}|j}x|D]}|j|q"W|jd|j}|jd|dS(s Adds all currently open displays to our list of displays, and set up a signal connection so that we'll be notified when displays are opened in the future as well. tdisplay_openeds user-callbackN(R R tdisplay_manager_gett list_displayst add_displayR+tdisplay_opened_cbtset_data(Rtmanagertdisplaystitemtid((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyt__initialize_displayss   cCs1tj|}tjtd}|jd|j|tj}|jtjtj |j tj |j |t t dtj}|jt|j||j}|jtjtjtd}|j |ttd|jdkrtjtj|_n|jj||||fS(s This function is used both for creating the "Display" and "Screen" frames, since they have a similar structure. The caller hooks up the right context for the value returned in tree_view, and packs any relevant buttons into button_vbox. iiiN(R RtHBoxR'RNRtScrolledWindowt set_policyt POLICY_NEVERtPOLICY_AUTOMATICRt SHADOW_INRPRtTreeViewtset_headers_visiblet get_selectiontset_modetSELECTION_BROWSERMt size_groupRt SizeGrouptSIZE_GROUP_HORIZONTALt add_widget(RttitleRthboxt scrollwint tree_viewt selectiont button_vbox((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyt__create_frames&       cCs|jd\}}}td}|jd|j|j|ttdtd}|jd|j|j|ttdtjt t |_ |j |j tj dtjdt}|j||j}|jd|j|S( s9 Creates the "Display" frame in the main window. tDisplays_Open...tclickedit_ClosetNamettexttchanged(t _ChangeDisplayDemo__create_frameR9R+topen_display_cbRPR'tclose_display_cbR t ListStoretstrtobjectt display_modelt set_modeltTreeViewColumntCellRendererTexttDISPLAY_COLUMN_NAMEt append_columnRhtdisplay_changed_cb(RRRrRttbuttontcolumnRs((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyt__create_display_frames     cCs|jd\}}}tjtt|_|j|jtjdtjdt }|j ||j |_ |j j d|j|S(s8 Creates the "Screen" frame in the main window. tScreentNumberRzR{(R|R RtintRt screen_modelRRRtSCREEN_COLUMN_NUMBERRRhtscreen_selectionR+tscreen_changed_cb(RRRrRtR((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyt__create_screen_frames  cCsW|jj}t|dj}|dk rC|j|jn|jjdS(s Prompts the user for a toplevel window to move, and then moves that window to the currently selected display s4Please select the toplevel to move to the new screenN( R&RRR3RR tcurrent_screenRtbeep(RRR2((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pytquery_change_displays  cCs*|tjkr|jn |jdS(s Called when the user clicks on a button in our dialog or closes the dialog through the window manager. Unless the "Change" button was clicked, we destroy the dialog. N(R RHRR.(Rtdialogt response_id((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRK s c CsFtjd|tjtjtjtjtjf}|jtjtj}|j t tj d}|j j ||j j ||j|jd}x|dkr7|j}|tjkrPn|jdd}|GH|dkrtjj|}|dkr4d|f}|j|q4qqW|jdS(s Called when the user clicks on "Open..." in the display frame. Prompts for a new display, and then opens a connection to that display. s Open Displays)Please enter the name of the new display iits0Can't open display : %s please try another one N(R RDt DIALOG_MODALt STOCK_CANCELtRESPONSE_CANCELtSTOCK_OKRHtset_default_responsetEntrytset_activates_defaultRRRORt grab_focusRRR3t get_charsR Rvtset_textR.( RRRt display_entryt dialog_labeltresultRtnew_screen_namet error_msg((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR}s0!        cCs|jr|jjndS(s| Called when the user clicks on the "Close" button in the "Display" frame. Closes the selected display. N(tcurrent_displaytclose(RR((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR~:s cCsM|j\}}|dk r6|j|t|_n d|_|jdS(s Called when the selected row in the display list changes. Updates info.current_display, then refills the list of screens. N(t get_selectedRt get_valuetDISPLAY_COLUMN_DISPLAYRt fill_screens(RRstmodeltiter((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRBs   cCsA|j\}}|r4|j|td|_n d|_dS(sk Called when the selected row in the sceen list changes. Updates info->current_screen. iN(RtgettSCREEN_COLUMN_SCREENRR(RRsRR((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRNscCs'|j|dkr#tjndS(N(t destroy_infoRR R@(RRT((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRLXs  cCs|jj|jdk r|jj}xst|D]b}|jj|}|jj}|jj|t |t ||dkr8|j j |q8q8WndS(s? Fills in the screen list based on the current display iN( RtclearRRt get_n_screenstrangeRtappendtsetRRRt select_iter(Rt n_screenstiRR((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR^s   cCsd|jj}xN|r_|jj|t}||krM|jj|Pn|jj}qWdS(st Called when one of the currently open displays is closed. Remove it from our list of displays. N(Rtget_iter_firstRRtremovet iter_next(RRtis_errortinfoRt tmp_display((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pytdisplay_closed_cbms  cCs`|j}|jj}|jj|t|t||jd|j}|jd|dS(s Adds a new display to our list of displays, and connects to the "closed" signal so that we can remove it from the list of displays again. tcloseds user-callbackN( tget_nameRRRRRR+RRZ(RRtnameRR^((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRXys   cCs|j|dS(s- Called when a new display is opened N(RX(RR[R((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRYscCshtjj}|j}|jd}|j|x*|D]"}|jd}|j|q>WdS(s Cleans up when the toplevel is destroyed; we remove the connections we use to track currently open displays. s user-callbackN(R R RVRWtget_datat disconnect(RR[R\R^ttmp_list((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRs   N(R6R7RRkRRRRRR RSR|RQRRRRKR}R~RRRLRRRXRYR(((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyR>~s.  #    $    cCsttjdS(N(R>R tmain(((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyRst__main__(R8tpygtktrequireR R#RRRtDISPLAY_NUM_COLUMNSRRtSCREEN_NUM_COLUMNSRR RR:R9RDR>RR6(((s+/usr/lib/pygtk27/2.0/demos/changedisplay.pyts     5